我对Q的简单性深信不疑,所以我可能没有做太多研究来检查其他"then"实现。但我用了Q很多!
我有一个"然后"的承诺链,我想解决中间的"一批"承诺,并按顺序进行其他操作;所以很明显我应该使用Q.all。但我被困在这里了。要么Q做错了,要么我做错了。
以下是两个假设的异步操作
var f=function(delay){
return Q.delay(delay).then(function(){
console.log("returning delayed",delay)
return delay
})
}
f2=function(delay){
var defer=Q.defer()
setTimeout(function(){
console.log("returning timedout",delay)
return delay
},delay)
return defer.promise
}
这就是承诺链
Q('begin')
.then(console.log)
.then(Q.all([100,200,300,400].map(f)))
.then(function(){
console.log("Finally",arguments)
}).done()
这是我希望的输出
begin
returning delayed 100
returning delayed 200
returning delayed 300
returning delayed 400
Finally { '0': undefined }
但这是我得到的输出
begin
Finally { '0': undefined }
returning delayed 100
returning delayed 200
returning delayed 300
returning delayed 400
我得到了与f2
相同的序列
现在,如果我运行这个
Q.all([100,200,300,400].map(f)).then(function(){
console.log("Finally",arguments)
}).done()
我有
returning delayed 100
returning delayed 200
returning delayed 300
returning delayed 400
Finally { '0': [ 100, 200, 300, 400 ] }
但是用CCD_ 2代替CCD_
returning timedout 100
returning timedout 200
returning timedout 300
returning timedout 400
它不执行finally
块。
我用Q.[allResolved/allSettled]得到相同的输出
所以,我的问题是,
- 我如何通过专门使用Q.all来实现预期的输出。我确实有一个变通办法,但看起来不太好
f
和f2
有什么不同,因为用它们运行Q.all((.then((的结果不一样
Q.all
接受一个promise数组,但返回一个prome(当数组中的每个promise都被解析时,这是唯一被解析的(。
因此,我认为您需要返回Q.all
的结果,以便不立即调用下一个then
:
Q('begin')
.then(console.log)
.then(function() {
return Q.all([100,200,300,400].map(f));
})
.then(function(){
console.log("Finally",arguments)
}).done()
在回答第二个问题时,您对f2
的使用是错误的。
当你使用延期创建承诺时,你必须解决它才能实现。您可以在如何将回调API转换为promise中了解更多信息。
在您的案例中,您创建了一个空的deferred并返回其promise,但实际上从未在deferred上调用.resolve
。"更正确"地做这件事就像:
f2=function(delay){
var defer=Q.defer()
setTimeout(function(){
console.log("returning timedout",delay)
defer.resolve(delay); // note the resolve here vs the return
},delay)
return defer.promise
}
使用Q.delay
效果更好,因为它已经被承诺了。至于其他then
实现,至少可以说Q现在几乎没有流血:(