为什么我的Deferred不运行错误方法?

时间:2015-05-26 13:19:46

标签: javascript promise ecmascript-6

我创建了这个简单的代码来模拟resolverejecterror

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);
  }
};

现在让我们调用它们:

$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

正如您所看到的,拒绝/解决方案都有效。

问题:

为什么不是:

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

当我模拟error时,函数会运行吗?

Full Jsbin

2 个答案:

答案 0 :(得分:3)

  

为什么没有

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

函数运行,当我模拟error

根据ECMA Script 6 Promise规范,当您使用Promise构造函数创建Promise时,创建的promise对象将具有两个内部插槽[[PromiseFulfillReactions]][[PromiseRejectReactions]],它们实际上是列表,它们将分别保存所有相应的履行和拒绝处理程序。

当您将then处理程序附加到promise对象时,履行处理程序将添加到[[PromiseFulfillReactions]]列表中,拒绝处理程序将添加到[[PromiseRejectReactions]]列表中。履行承诺后,将调用[[PromiseFulfillReactions]]中的所有处理程序,类似情况,当状态从pending更改为rejected时,将调用所有拒绝处理程序。

在这两种情况下,

$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')$http().simulate('error')创建新的承诺,当您附加then处理程序时,callback.successcallback.reject会添加到相应的反应列表中。在这两种情况下,抛出Error并拒绝将被视为仅拒绝承诺。由于[[PromiseRejectReactions]]中只有一个处理程序用于执行两种情况。这就是为什么在这两种情况下只调用callback.reject的原因。

如果您已定义最后一个案例,例如

,该怎么办?
$http().simulate('error')
       .then(callback.success)
       .catch(callback.error);

现在,then处理程序没有onRejected处理程序。但需要注意的重点是,所有 then处理程序都将创建新的承诺并将其返回。因此,由于拒绝处理程序不适用于当前then,因此它将创建被拒绝的承诺并将其返回。 .catch(callback.error)只是.then(undefined, callback.error) 的语法糖。被拒绝的承诺的拒绝反应列表将获得callback.error函数,并且将被调用,因为承诺被拒绝。

答案 1 :(得分:0)

这是因为你的callback.reject方法本身正在处理抛出的错误。如果您希望调用callback.error,则需要将callback.reject方法修改为throw错误本身或将其return Promise.reject(data)

相关问题