Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using success/error/finally/catch with Promises in AngularJS

Promises are an abstraction over statements that allow us to express ourselves synchronously with asynchronous code. They represent a execution of a one time task.

They also provide exception handling, just like normal code, you can return from a promise or you can throw.

What you'd want in synchronous code is:

try{
  try{
      var res = $http.getSync("url");
      res = someProcessingOf(res);
  } catch (e) {
      console.log("Got an error!",e);
      throw e; // rethrow to not marked as handled
  }
  // do more stuff with res
} catch (e){
     // handle errors in processing or in error.
}

The promisified version is very similar:

$http.get("url").
then(someProcessingOf).
catch(function(e){
   console.log("got an error in initial processing",e);
   throw e; // rethrow to not marked as handled, 
            // in $q it's better to `return $q.reject(e)` here
}).then(function(res){
    // do more stuff
}).catch(function(e){
    // handle errors in processing or in error.
});

Forget about using success and error method.

Both methods have been deprecated in angular 1.4. Basically, the reason behind the deprecation is that they are not chainable-friendly, so to speak.

With the following example, I'll try to demonstrate what I mean about success and error being not chainable-friendly. Suppose we call an API that returns a user object with an address:

User object:

{name: 'Igor', address: 'San Francisco'}

Call to the API:

$http.get('/user')
    .success(function (user) {
        return user.address;   <---  
    })                            |  // you might expect that 'obj' is equal to the
    .then(function (obj) {   ------  // address of the user, but it is NOT

        console.log(obj); // -> {name: 'Igor', address: 'San Francisco'}
    });
};

What happened?

Because success and error return the original promise, i.e. the one returned by $http.get, the object passed to the callback of the then is the whole user object, that is to say the same input to the preceding success callback.

If we had chained two then, this would have been less confusing:

$http.get('/user')
    .then(function (user) {
        return user.address;  
    })
    .then(function (obj) {  
        console.log(obj); // -> 'San Francisco'
    });
};

I think the previous answers are correct, but here is another example (just a f.y.i, success() and error() are deprecated according to AngularJS Main page:

$http
    .get('http://someendpoint/maybe/returns/JSON')
    .then(function(response) {
        return response.data;
    }).catch(function(e) {
        console.log('Error: ', e);
        throw e;
    }).finally(function() {
        console.log('This finally block');
    });

What type of granularity are you looking for? You can typically get by with:

$http.get(url).then(
  //success function
  function(results) {
    //do something w/results.data
  },
  //error function
  function(err) {
    //handle error
  }
);

I've found that "finally" and "catch" are better off when chaining multiple promises.