declaring a promise in angularJS with named success/error callbacks

13,715

Solution 1

The nice thing with open-source is that you can read the source. Here's how the $http service does it:

  promise.success = function(fn) {
    promise.then(function(response) {
      fn(response.data, response.status, response.headers, config);
    });
    return promise;
  };

  promise.error = function(fn) {
    promise.then(null, function(response) {
      fn(response.data, response.status, response.headers, config);
    });
    return promise;
  };

Solution 2

You need to use the $q service and create and return your own promise in GetUserProfile:

function GetUserProfile() {
    var deferred = $q.defer();
    var promise = deferred.promise;

    // success condition
    if (!true) {
        deferred.resolve('data');
    // error condition
    } else {
        deferred.reject('error');
    }

    promise.success = function(fn) {
        promise.then(fn);
        return promise;
    }

    promise.error = function(fn) {
        promise.then(null, fn);
        return promise;
    }

    return promise;
}

GetUserProfile()
    .success(function(data) {
        console.log(data);
    })
    .error(function(error) {
        console.error(error);
    });

Solution 3

You don't need change source code. Angular provide a way to change any service in angular include $q.

$provide.decorator is perfect for your requirement here is my code.

put it at app.module('...').config

$provide.decorator('$q', function($delegate) {
  function httpResponseWrapper(fn) {
    return function(res) {
      if (res.hasOwnProperty('data') && res.hasOwnProperty('status') && res.hasOwnProperty('headers') && res.hasOwnProperty('config') && res.hasOwnProperty('statusText')) {
        return fn(res.data, res.status, res.headers, res.config, res.statusText);
      } else {
        return fn(res);
      }
    };
  };
  function decorator(promise) {
    promise.success = function(fn) {
      return decorator(promise.then(httpResponseWrapper(fn)));
    };
    promise.error = function(fn) {
      return decorator(promise.then(null, httpResponseWrapper(fn)));
    };
    return promise;
  };
  var defer = $delegate.defer;
  $delegate.defer = function() {
    var deferred = defer();
    decorator(deferred.promise);
    return deferred;
  };
  return $delegate;
});
Share:
13,715

Related videos on Youtube

Nuno_147
Author by

Nuno_147

Updated on November 01, 2022

Comments

  • Nuno_147
    Nuno_147 over 1 year

    I am trying to do something very similar to the $http service. From my understanding $http return a promise object.

    When using it the syntax is :

    $http(...).success(function(data)) {
       //success callback
    }).error(function(data)) {
       //error callback
    })
    

    I would like to do just the same but consider my API is GetUserProfile, so I wish to have the syntax :

    GetUserProfile(...).success(function(data) {
       // success callback
    }).error(function(data)) {
       // error callback
    })
    

    how can I accomplish that using a promise ?

  • Nuno_147
    Nuno_147 over 10 years
    I am aware of it.. but still the success/error syntax used in $http will not apply here. or maybe it will ? is the success/error syntax is by default used when a promise returned ?
  • katranci
    katranci over 10 years
    I misunderstood the question. No, the promise object doesn't have success and error methods by default.
  • katranci
    katranci over 10 years
    I've edited my answer and added the success/error methods to the promise object.
  • nwayve
    nwayve almost 10 years
    Response interceptors are deprecated in 1.3+, but the same concept still applies. Use something like: promise.success = function (fn) { return promise.then(fn); }); promise.error = function (fn) { return promise.then(null, fn); });
  • Rob S
    Rob S over 9 years
    Most responses for how to do this breaks the ability to chain promises together whereas your solution preserves that capability, I prefer your answer.