Promises:.done()总是执行,即使.catch()是?

时间:2015-11-26 21:40:27

标签: javascript node.js promise q

我的承诺问题

我是Promises的新手,我一直在阅读Q Documentation,其中说的是:

  

当你到达承诺链的末尾时,你应该返回最后的承诺或结束链。

我已经在我的代码中以Q.Promise方式定义了一个Promise,并使用以下console.log来注销执行跟踪:

function foo(){
   return Q.Promise(function(resolve, reject) {

    doSomething()
    .then(function() {
      console.log('1');
      return doSomething1();
    })
    .then(function() {
      console.log('2');
      return doSomething2();
    })
    .then(function() {
      console.log('3');
      return doSomething3();
    })
    .catch(function(err) {
      console.log('catch!!');
      reject(err);
    })
    .done(function() {
      console.log('done!!');
      resolve();
    });

  });
}

如果每个doSomethingN()正确执行,一切都按预期工作,我得到预期的跟踪:

1
2
3
done!!

,以防任何doSomethingN()失败:

foo()正常工作,因为错误函数回调是在reject(err)发生时运行的回调:

foo().then(function() { /* */ }, function(err) { /* this runs! */ });

我得到以下跟踪(即doSomething1()失败时):

1
catch!!
done!!

我的问题

我最初的想法如下:

  

好的,让我们在.done().catch()方法中处理链接成功失败。如果一切顺利,.done()将执行回调并且承诺将解决。如果在任何时候出现错误,将执行.catch()的回调并且承诺将被拒绝 - 正因为如此,{{1}不会被执行。

我想我错过了关于done()如何工作的事情......因为通过查看我的日志记录,我意识到.done()似乎总是在执行 - 是否有错误并且.done()已执行或未执行 - 而这正是我所期待的。

因此,在此之后,我删除了.catch()的回调,现在.done()

  • 在链执行期间foo()
  • 时有效 如果一切正常,
  • 不起作用

我应该重新考虑什么?我应该如何/应该让它发挥作用?

3 个答案:

答案 0 :(得分:5)

catch(cb)只是then(null, cb)的别名,您实际上已修复错误catch,因此流程自然转向成功结果为done

如果你只想装饰 catch中的错误,你应该在之后重新抛出错误,例如:适当的passthru可能看起来像:

catch(function (err) {
   console.log(err);
   throw err;
});

你的例子仍然没有多大意义。当你返回一个承诺时,你永远不应该使用done。如果要使用内部创建的promise链解决初始化的promise,则应将其解析为:

resolve(doSomething()
  .then(function() {
    console.log('1');
    return doSomething1();
  })
  ....
  .then(function() {
    console.log('N');
    return doSomethingN();
  }));

不需要内部错误处理,将其留给您返回的承诺消费者。

还有其他一点。如果在创建新承诺时,您知道它将与其他承诺一起解决,那么创建此类承诺没有合理的理由,只需重用您计划解决的承诺。这种错误也被创造为deferred anti-pattern

答案 1 :(得分:2)

你应该考虑这样做:

fstream& Go2Line(fstream& file, unsigned int num){
file.seekg(ios::beg);
for(unsigned int i=0; i < num - 1; ++i)
    file.ignore(numeric_limits<streamsize>::max(),'\n');
return file;}



int main(){ 
fstream file("testo.csv",ios_base::in);
if (!file)
    cout << "Unable to open file file.csv\n";
else
{
    int Number2Go = 1;
    Go2Line(file, Number2Go);

    if (!file)
        cout << "Unable to reach line " << Number2Go << ".\n";
    else
    {
        string line;
        getline(file,line);
        std::stringstream convertor(line);// I Don't know how continue from here

    }
}

return 0;}

如果你想返回一个承诺,在大多数情况下使用catch没有多大意义(除非你想恢复潜在的错误)。在返回promise的方法中使用function foo() { // Calling .then() on a promise still return a promise. // You don't need Q.Promise here return doSomething() .then(function(doSomethingResult) { console.log('1'); return doSomething1(); }) .then(function(doSomething1Result) { console.log('2'); return doSomething2(); }) .then(function(doSomething2Result) { console.log('3'); return doSomething3(); }); } foo() .then(function(fooResult) { console.log(fooResult); // fooResult should be what is returned by doSomething3() }) .catch(function(err) { console.error(err); // Can be thrown by any }) .done(function() { console.log('I am always executed! error or success'); }); 永远不会有意义。你宁愿在链的最后使用这些方法。

请注意,done可以返回值或承诺,它将起作用。

答案 2 :(得分:0)

您可以通过在上一次然后回调中解析承诺来使其发挥作用。

function foo(){
    return doSomething()
    .then(function() {
      console.log('1');
      return doSomething1();
    })
    .then(function() {
      console.log('2');
      return doSomething2();
    })
    .then(function() {
      console.log('3');
      return doSomething3();
    })
}

考虑将bluebird用于承诺。与任何其他promise库相比,它具有许多有用的功能。你可能会发现它很难开始,但是一旦掌握了它,你就会喜欢它。