我遇到了article about promises in js,作者在其中显示了一段代码:
// I want to remove() all docs
db.allDocs({include_docs: true}).then(function (result) {
result.rows.forEach(function (row) {
db.remove(row.doc);
});
}).then(function () {
// I naively believe all docs have been removed() now!
});
并说
此代码有什么问题?问题是第一个问题 函数实际上是返回undefined,意思是第二个 函数不等待所有的db.remove()被调用 文档。实际上,它不是在等待任何东西,而是可以在何时执行 已删除任意数量的文档!
所以,据我所知,如果第二个回调function() {}
不接受任何参数,它实际上不会等待回调结束function(result)
。我是否正确推断?因为当我运行以下代码时,它给出了相反的结果:
var array = [];
for ( let i = 0; i < 1000; i++ )
array.push(i);
var promise = new Promise((resolve, reject) => {
setTimeout(() => resolve(), 1000);
});
promise
.then(() => array.forEach(item => console.log(item)))
.then(() => console.log("invoked earlier"));
我等待“先前调用”出现在打印数字的中间。但无论物品的数量有多大都无关紧要。 “先前调用”总是出现在最后。有人可以解释我错过了什么吗?也许这篇文章已经过时了,从那以后发生了一些变化?
答案 0 :(得分:4)
为了保证这一点,你实际上必须从先前的承诺中返回承诺。
无论您从承诺中返回,都会被传递到下一个承诺。
在您的情况下,您返回undefined
。
相反,如果您返回了一个承诺,那么承诺将被解决,第二个承诺将在发生之后运行,并且将传递承诺解决的任何值。
所以是的,承诺保证会一个接一个地运行,但是如果你选择在回调中做一些异步,并且不想通过返回将它链接回承诺,那么他们就可以了。我不愿意等待任何事情(因为他们不知道还有什么需要等待的。)
我假设db.remove
返回承诺......
...所以,知道我们必须从回调中返回一个promise,为了让它实际等待异步事件发生,我会做这样的事情。
.then(result => Promise.all(result.rows.map(row => db.remove(row.doc))))
.then((listOfRemoves) => console.log(`removed`));
第二个函数运行时,第二个函数是1还是0参数是100%无关紧要的。
的示例:
.then(() => setTimeout(() => console.log('2nd', 20000)))
.then(() => console.log('first'));
这是因为第一个不知道发生了setTimeout。它不是一个读者,只是运行代码并传递返回值(在本例中为undefined
)。
如果返回值恰好是一个承诺,它将等到该承诺完成,从中获取值,然后传递 。
.then(() => new Promise(resolve => setTimeout(resolve, 20000)))
.then(() => console.log('I waited 20 seconds.'));
因为它会返回一个承诺,它会调用该承诺的then
,并等待获取该值,然后传递。
您的测试失败的原因是因为您基本上是这样做的。
.then(() => console.log('first'))
.then(() => console.log('second'));
这些保证按此顺序触发。期。 所有其他的也按顺序开火。只是他们也调度异步进程,就像在JS中使用异步I / O的所有其他回调/超时一样。