Javascript 承诺:即使.catch()是,也总是执行.done()吗? 我的承诺问题
我不熟悉《承诺》,我一直在阅读《承诺》,其中写道: 当你到达承诺链的末端时,你应该要么返回最后一个承诺,要么结束承诺链 我在我的代码中以Javascript 承诺:即使.catch()是,也总是执行.done()吗? 我的承诺问题,javascript,node.js,promise,q,Javascript,Node.js,Promise,Q,我不熟悉《承诺》,我一直在阅读《承诺》,其中写道: 当你到达承诺链的末端时,你应该要么返回最后一个承诺,要么结束承诺链 我在我的代码中以Q.Promise的方式定义了一个承诺,使用以下console.logs注销执行跟踪: function foo(){ return Q.Promise(function(resolve, reject) { doSomething() .then(function() { console.log('1'); re
Q.Promise
的方式定义了一个承诺,使用以下console.log
s注销执行跟踪:
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()
失败:
1
catch!!
done!!
foo()
工作正常,因为每当发生拒绝(err)
时,都会运行错误函数回调:
foo()代码>
我得到以下跟踪(即当doSomething1()
失败时):
我的问题
我最初的想法是:
好的,让我们同时处理.done()
和.catch()
方法中的链接success和failure。如果一切顺利,.done()
的回调将被执行,承诺将得到解决。如果在任何时候出现错误,.catch()
的回调将被执行,承诺将被拒绝,因此,done()
将不会执行
我想我遗漏了一些关于.done()
如何工作的信息。。。因为通过查看我的日志记录跟踪,我意识到.done()
似乎总是在执行-无论是否存在错误以及.catch()
是否执行-这是我没有预料到的
因此,在那之后,我删除了.done()
的回调,现在是foo()
:
- 如果在链执行过程中出现
错误
,则此功能有效
- 如果一切正常,则不起作用
我应该重新考虑什么?我应该如何使它工作?您可以通过在最后一次回拨中解决承诺来使它工作
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();
})
}
考虑使用“承诺”。与任何其他promise库相比,它有许多有用的特性。你可能发现很难开始,但是一旦你抓住它,你就会爱上它。 < P>你应该考虑这样做:
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');
});
如果您想要返回承诺,在大多数情况下,使用catch没有多大意义(除非您想要恢复潜在的错误)。在返回承诺的方法中使用done
是没有意义的。您宁愿在链的最末端使用这些方法
请注意,doSomethingX()
可以返回一个值或一个承诺,它的工作原理是一样的。catch(cb)
只是then(null,cb)
的别名,实际上您已经修复了catch
中的一个错误,因此流自然会变成done
中的成功结果
如果您只想修饰catch中的错误,则应在之后重新显示该错误,例如,正确的passthru可能如下所示:
catch(function (err) {
console.log(err);
throw err;
});
你的例子仍然没有多大意义。当您返回承诺时,绝不应使用done
。如果您希望使用内部创建的承诺链解析初始化的承诺,则应将其解析为:
resolve(doSomething()
.then(function() {
console.log('1');
return doSomething1();
})
....
.then(function() {
console.log('N');
return doSomethingN();
}));
不需要进行内部错误处理,将其交给承诺的消费者处理
还有一点。如果在创建新的承诺时,您知道它将与其他承诺一起解决,那么创建这样的承诺就没有逻辑上的理由,只需重复使用您计划与之解决的承诺即可。这种错误也被创造为首先,避免错误!您的问题不在于done
,而在于catch
。捕获错误意味着您已经处理了错误,并且从.catch(…)
返回的承诺(您附加到.done()
的承诺)将得到履行@Bergi恐怕我不明白你在第二次评论中想解释什么。。。这个.catch()
有什么问题?它返回一个最终会实现的承诺,这就是为什么即使出现错误,done
也会运行的原因。看看@Bergi,你给出的关于这个主题的链接非常有用!当所有doSomethingN呼叫都解决后,它仍然不起作用吗?我同意@Bergi的观点。@KunalKapadia:不,它按照你的意图“起作用”,但你的回答仍然显示出不好的做法@KunalKapadia,我正在寻找正确的解决方案。我以前已经考虑过你的解决方案,但因为Bergi的话,我放弃了它。@Bergi同意你的看法。从我的代码中删除了反模式。指出得很好,解释得很清楚,@SebastienLorber!我还有最后一个问题,关于在哪里使用延迟
或新承诺
:因此,我应该只使用这些(一个或另一个)在函数中进行“设置”,我希望返回承诺。在这种情况下,在foo()
中,您不需要延迟
或新承诺
,因为这已经在每个doSomethingN()
(已经返回承诺)中完成,您可以通过直接获得这些承诺。。。我说得对吗?我想我明白这是怎么回事了。。。!和@SebastienLorber,如果任何doSomethingN()
函数抛出了拒绝
。。。如果你的dosothingx()
操作不需要使用之前要执行的结果,你可以并行启动它们(使用Q.all([smth1Promise,smth2Promise,smth3Promise])。spread(res1,res2,res3)
…非常好。我唯一的问题是:用resolve()
包装链有什么区别?区别与resolve(promise)
和promise.done(resolve,reject)
相同。两者都会做完全相同的事情,仍然是f