【问题标题】:Why does deferred.resolve not behave as specified in the q manual?为什么 deferred.resolve 的行为不像 q 手册中指定的那样?
【发布时间】:2014-01-05 03:00:25
【问题描述】:

这可能是一个愚蠢的问题,但我无法解决这个问题。

考虑以下代码:

function throwError() {
    throw Error("can't touch this.");
}

var def = q.defer();

def.promise.then(
  function() {
    console.log("no error");
  },
  function() {
    console.log("error");
  }
);

q.fcall(throwError).then(def.resolve, def.resolve).done();

在我看来,这应该打印error。相反,它打印no errorq 手册指出:

reject 函数是用rejected 解决的简写 承诺。

q.fcall(throwError) 应该产生一个被拒绝的承诺,所以 deferred 应该被拒绝,对吧?

请注意,这是一个纯粹的假设问题,我知道这不会在现实世界中使用。

【问题讨论】:

    标签: javascript node.js q


    【解决方案1】:

    这里的问题似乎与所使用的语言有关,因此我将尝试将其进一步分解以使其更清晰。当你打电话时

    var rejected = q.fcall(throwError);
    

    那么rejected 确实是一个被拒绝的承诺。然后你正在做的是

    var def = q.defer();
    def.promise.then(
      function(arg1) {
        console.log("no error");
      },
      function(arg2) {
        console.log("error");
      }
    );
    
    rejected.then(
      function(){
        def.resolve();
      },
      function(err){
        def.resolve(err); // err === new Error();
      }
    );
    

    当一个 promise 被拒绝时,它会运行拒绝回调,触发def.resolve(err);。 Q 不知道def 只是一些随机参数,所以你不妨打电话给def.resolve('random');。你正在用一些论点解决def。在这种情况下,它恰好是Error 的一个实例。这意味着您的no error 回调将被调用,arg1 === new Error()

    现在,鉴于您提到的文档引用

    reject 函数是解决被拒绝承诺的简写。

    您所做的实际上是将被拒绝的承诺rejected 转换为承诺def.promise,这将始终被履行,但履行处理程序将收到错误作为第一个参数。

    要达到您的期望,您需要正确地拒绝def.promise。您可以通过两种方式完成。

    1. 使用def.reject(err); 拒绝它。
    2. 正如您的报价所说,使用被拒绝的承诺来解决它,def.resolve(rejected);

    【讨论】:

    • 其实我想用两次def.resolve。如上所述,使用被拒绝的 Promise 解决应该触发错误处理程序,而不是履行处理程序。所以,IMO,应该调用第二个函数,而不是第一个。
    • @raffomania 对不起,没有关注。正如你所说,q.fcall(throwError) 确实产生了一个被拒绝的承诺,但是由于你已经将 def.resolve 作为错误处理程序传递了,它会在没有错误的情况下解析 def,就像你在其他地方调用 def.resolve() 一样。
    • 也许困惑在于resolving with a rejected promise. 你现在正在做的是用Error 对象解决,而不是用被拒绝的承诺解决。
    • 请看这里:Using deferreds in q。在那里你可以看到我的例子。 q.fcall 应该产生一个被拒绝的承诺,而不是一个错误。
    • @raffomania 正确,fcall 的返回值返回一个被拒绝的承诺。然后您调用.then,它提取与拒绝相关的错误,并将该错误作为第一个参数传递。我会扩展我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多