1

I'm trying to compare two approaches of using promises in angular after reading this article.

So I use this code to compare with/without using deferred. Note: the adress http://localhost:1337/error returns a response with an http 500 status and a message "error" as error data (it is the intended behavior).

.controller("HomeCtrl", function($q, $http) {
    function doAsyncCallDeferred() {
        var deferred = $q.defer();
        $http.get("http://localhost:1337/error")
            .catch(function(errorData) {
                // error
                deferred.reject(errorData.data);
            });
        return deferred.promise;
    }

    function doAsyncCall() {
        return $http.get("http://localhost:1337/error")
            .catch(function(errorData) {
                // error
                return errorData.data;
            });
    }

    doAsyncCallDeferred()
        .then(function (data) {
            console.log("with deferred success");
            console.log(data);
        })
        .catch(function(errorData) {
            // data should be "error"
            console.log("with deferred error");
            console.log(errorData);
        });

    doAsyncCall()
        .then(function (data) {
            console.log("without deferred success");
            console.log(data);
        })
        .catch(function(errorData) {
            // data should be "error"
            console.log("without deferred error");
            console.log(errorData);
        });
})

But I am confused by the result :

with deferred error
error
without deferred success
error

I was assuming that with both approaches, the catch callback would be executed, but it seems that it's not the case. Do anyone can explain this behavior please ?

Xartok
  • 346
  • 3
  • 13
  • I guess it is because this line: `deferred.reject(errorData.data);`. It rejects the deferred, so outside the function still catchable. Could you verify? – Joy Jul 31 '15 at 16:09
  • Avoid the [deferred antipattern](http://stackoverflow.com/q/23803743/1048572) (in `doAsyncCallDeferred`)! Notice that you're never fulfilling the deferred when the ajax call succeeds. – Bergi Jul 31 '15 at 16:36
  • 1
    @Bergi, he *is* trying to avoid it - the first link is to the article about deferred antipattern – New Dev Jul 31 '15 at 16:38
  • @NewDev: Oh, right. I should read the questions more carefully. – Bergi Jul 31 '15 at 16:39
  • @Joy it rejects the rejected promise data, the string "error" – Xartok Jul 31 '15 at 17:15

1 Answers1

2

.then and .catch are the async "equivalent" of try/catch. When you .catch something, it means that you "handled" it.

In doAsyncCall you are handling the "exception" (which is a promise rejection) and returning errorData.data as data to the next .then. If you want to "re-throw", then return $q.reject(errorData.data).

In doAsyncCallDeferred you are explicitly rejecting a promise.

By way of example, the following are equivalent to their users:

function doAsyncCallDeferred() {
    var deferred = $q.defer();
    $http.get("http://httpstat.us/500")
        .then(function(response){
           deferred.resolve(response.data);
        })
        .catch(function(errorData) {
           deferred.reject(errorData.data);
        });
    return deferred.promise;
}

function doAsyncCall() {
    return $http
             .get("http://httpstat.us/500")
             .then(function(response){
                return response.data;
             })
             .catch(function(errorData){
                return $q.reject(errorData.data);
             });

}
New Dev
  • 48,427
  • 12
  • 87
  • 129