Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't my Deferred run the error method?

I have created this simple code to simulate resolve , reject , error :

function $http(){
  var core = {
    factory : function (action) {
      var promise = new Promise( function (resolve, reject) {

        if (action==='resolve')  resolve({r:'Resolved'});
        if (action==='error')    throw Error("error");
        if (action==='reject')   reject({r:'Reject'});
      });
      return promise;

  } 
  };
  return {
    'simulate' : function(a) {
      return core.factory(a);
    }
  };
}

var callback = {
  success : function(data){
     console.log(1, 'success', data.r);
  },
  error : function(data){
     console.log(2, 'error',data.r);
  },
   reject : function(data){
     console.log(3, 'reject', data.r);
  }
};

Now let's invoke them :

$http().simulate('resolve')
       .then(callback.success,callback.reject)
       .catch(callback.error); //"success" "Reolved"

$http().simulate('reject')
       .then(callback.success,callback.reject)
       .catch(callback.error); //"reject" "Reject"

$http().simulate('error')
       .then(callback.success,callback.reject)
       .catch(callback.error);//"reject" undefined

As you can see both reject/resolve are working.

Question:

Why doesn't the :

 error : function(data){
     console.log(2, 'error',data.r);
  }

Function runs , when I simulate error ?

Full Jsbin

like image 519
Royi Namir Avatar asked Jul 11 '26 19:07

Royi Namir


1 Answers

Why doesn't the

error : function(data){
    console.log(2, 'error',data.r);
}

function run, when I simulate error?

As per the ECMA Script 6 Promise specifications, when you create a Promise with Promise constructor, the promise object created will have two internal slots, [[PromiseFulfillReactions]] and [[PromiseRejectReactions]], which are actually lists and they will hold all the corresponding fulfill and reject handlers respectively.

When you attach a then handler to a promise object, the fulfillment handler will be added to [[PromiseFulfillReactions]] list and the rejection handler will be added to [[PromiseRejectReactions]] list. When the promise is fulfilled, all the handlers in [[PromiseFulfillReactions]] will be invoked, similarly when the state changes from pending to rejected all the rejection handlers will be invoked.

In both these cases,

$http().simulate('reject')
       .then(callback.success, callback.reject)
       .catch(callback.error);   //"reject" "Reject"

$http().simulate('error')
       .then(callback.success, callback.reject)
       .catch(callback.error);  //"reject" undefined

$http().simulate('reject') and $http().simulate('error') create new promises and when you attach then then handler, the callback.success and callback.reject get added in to the respective reactions list. In both the cases, throwing an Error and rejecting will be treated as rejecting the promise only. Since there is only one handler in the [[PromiseRejectReactions]] for both the cases that is executed. That is why only callback.reject is called on both the occasions.


What if you have defined the last case, like this

$http().simulate('error')
       .then(callback.success)
       .catch(callback.error);

Now, the then handler doesn't have a onRejected handler. But the important point to be noted here is, all the then handlers will be creating new promises and return them. So, since the rejection handler is not available with the current then, it will create a rejected promise and return it. And the .catch(callback.error) is just syntactic sugar for .then(undefined, callback.error). The rejected promise's reject reactions list will get the callback.error function and that will be invoked, as the promise is rejected.

like image 172
thefourtheye Avatar answered Jul 13 '26 11:07

thefourtheye



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!