Search code examples
angularjsextendoverridingpromiseangularjs-service

How can I extend $q promise in Angularjs with a .success and .error


I wrote this little code in a custom service in AngularJS.

In my service:

        var deferred = $q.defer();
        var promise = deferred.promise;

        deferred.resolve('success');
        deferred.reject('error');

        /* Handle success and error */
        promise.success = function(fn) {

            promise.then(function(response) {

                fn(response);

            });

            return promise;
        };

        promise.error = function(fn) {

            promise.then(null, function(response) {

                fn(response);

            });

            return promise;
        };

In my controller:

        promiseService.myPromise()
            .success(function(data){

                $scope.success= data;

            })
            .error(function(data){

                $scope.error = data;

            });

I juste Handle the Success and Error from the promise ($q service). I need this code in a lot of other service so I would to extend directly the $q service with a custom.

So I would like something like this in my service:

    var deferred = myPromiseService.$qCustom.defer();
    var promise = deferred.promise;

    deferred.resolve('success');
    deferred.reject('error');

    return promise;

Any idea? I found some explanation to extend filter in Angularjs my problem is to find the good way to extend all the functionality of the $q and add my custom.

I start with something like that, it's work to handle the $q out of the box :

angular.module('myApp').service('myPromiseService', function($q){

  $qCustom = $q;  

});

Solution

  • Here's a full solution picking up where @jessegavin left off.

    var myApp = angular.module("myApp", []);
    
    myApp.config(function ($provide) {
    
      $provide.decorator('$q', function ($delegate) {
        var defer = $delegate.defer;
        $delegate.defer = function () {
          var deferred = defer();
          deferred.promise.success = function (fn) {
            deferred.promise.then(function(response) {
              fn(response.data, response.status, response.headers);
            });
          return deferred.promise;
          };
          deferred.promise.error = function (fn) {
            deferred.promise.then(null, function(response) {
              fn(response.data, response.status, response.headers);
            });
            return deferred.promise;
          };
          return deferred;
        };
        return $delegate;
      });
    
    });