我想使用Promise.all()执行一组promise。我的方法是将这些promise放在一个数组中,然后将数组传递给Promise.all()。但是,我发现promises在声明后立即开始执行,甚至不等待Promise.all被调用。
为什么会发生这种情况?如何才能让Promise仅在调用Promise.all()时执行?
let promiseArray = [];
const values = [1, 2, 3, 4, 5];
values.forEach((value)=>{
promiseArray.push(
new Promise((resolve, reject)=>{
console.log('value: ' + value);
return resolve();
})
)
})
console.log('start')
Promise.all(promiseArray)
/*
output is
value: 1
value: 2
value: 3
value: 4
value: 5
start
would have expected output to have been
start
value: 1
value: 2
value: 3
value: 4
value: 5
*/

答案 0 :(得分:3)
将承诺视为“执行”让你感到困惑。承诺纯粹是一种通知机制。它通常与某些底层异步操作绑定,当您创建promise时,通常会启动异步操作。
然后 Promise.all()
用于跟踪您已经开始的一大堆异步操作何时完成(或以错误结束)。
所以,你不要用Promise.all()
来开始一堆事情。您只是用它来跟踪它们何时完成,并在代码的其他位置启动它们。
当您使用new Promise()
手动创建承诺时,将立即执行承诺执行程序。这就是它们的设计方式。
如果您的承诺执行者中有真正的异步操作,并且当这些操作完成时您正在执行console.log()
,那么您可能不会发现如何设计承诺的任何问题。我认为你的大部分困惑源于你的诺言执行者内部实际上没有任何异步操作的事实,因此实际上没有理由甚至使用诺言。 Promise旨在跟踪异步操作的完成情况。如果您没有实际的异步操作,没有理由使用它们。
仅供参考,如果您想在将来的某个时间从承诺执行者内部开始一些异步操作,您可以使用正常的setTimeout()
或process.nextTick()
或setImmediate()
操作来安排以后开始的操作。
预期输出
另外,您似乎期望您的输出严格按顺序排列。 Promise.all()
期望并行运行N个异步操作,并且这些N个操作没有保证完成的完成顺序。相反,Promise.all()
将跟踪所有结果,收集所有结果并按顺序向.then()
处理程序提供一系列结果(如果它们都已成功解析)。它不会按顺序运行操作。这些操作并行运行,并按照自然顺序完成。
答案 1 :(得分:1)
是的,承诺立即执行。他们无法以任何其他方式工作。与JS中的任何其他对象一样,Promise完全不知道引用它们的内容以及它们如何被传递,因此它们无法“等待”直到某些特定内容完成对它们的引用。
您的案例中的解决方案是在将承诺传递给Promise.all()
时创建承诺:
let promiseFnArray = [];
const values = [1, 2, 3, 4, 5];
values.forEach((value) => {
promiseFnArray.push((resolve, reject) => {
console.log('value: ' + value);
return resolve();
}))
})
console.log('start')
Promise.all(promiseFnArray.map(promiseFn => new Promise(promiseFn));
此外,一旦您的承诺实际上使某些异步,它们将不一定按原始顺序解决。要以正确的顺序获得结果,请使用Promise.all( ... ).then()
,这是Promise.all()
的全部目的