我有此代码段,应await
5个承诺,暂停2秒,然后继续await
另外5个。但是,输出显示未等待两个Promise.all
尽管当我尝试在Promise中返回值时,它会正确返回。我是否理解Promise.all
的概念错误,或者我的代码中缺少某些内容?
(function () {
let val = 0
const promiseArr = []
for (let i = 0; i < 10; i++) {
promiseArr[i] = new Promise((res) => {
val += 500
setTimeout((val2) => {
console.log(val2)
res()
}, val, val)
})
}
console.log();
(async function() {
await Promise.all(promiseArr.slice(0, 5))
console.log('start await')
await new Promise((res) => setTimeout(res, 2000))
console.log('done await')
await Promise.all(promiseArr.slice(6, 10))
})()
}) ()
预期输出:
500
...
2500
start await
done await
3000
...
5000
实际输出:
500
1000
1500
2000
2500
start await
3000
3500
4000
4500
done await
5000
编辑: 现在我明白了为什么会这样。似乎我对Promises误解了一个基本概念。谢谢你们的帮助!
答案 0 :(得分:2)
您之所以会看到这种情况,是因为承诺创建后即开始(或者,无论如何,当前同步块完成时)就开始运行,而不是await
被启用时开始。
稍微整理一下代码,为每个事件打印时间戳可能会启发您:
const t0 = +new Date();
const logWithTime = (message = "") =>
console.log("" + Math.round(+new Date() - t0) + ": " + message);
(async function() {
let val = 0;
const resolver = res => {
val += 500;
const thisVal = val; // so we have a binding for the effective value
logWithTime("Creating timeout for " + thisVal);
setTimeout(
arg => {
logWithTime("Timeout for " + thisVal);
res();
},
thisVal,
thisVal,
);
};
const promiseArr = [];
for (let i = 0; i < 10; i++) {
promiseArr[i] = new Promise(resolver);
}
logWithTime("awaiting for first 5...");
await Promise.all(promiseArr.slice(0, 5));
logWithTime("waiting for 2 seconds...");
await new Promise(res => setTimeout(res, 2000));
logWithTime("waiting for the rest...");
await Promise.all(promiseArr.slice(6, 10));
logWithTime("all done");
})();
打印
0: Creating timeout for 500
10: Creating timeout for 1000
10: Creating timeout for 1500
10: Creating timeout for 2000
10: Creating timeout for 2500
10: Creating timeout for 3000
10: Creating timeout for 3500
10: Creating timeout for 4000
10: Creating timeout for 4500
10: Creating timeout for 5000
10: awaiting for first 5...
511: Timeout for 500
1011: Timeout for 1000
1515: Timeout for 1500
2013: Timeout for 2000
2510: Timeout for 2500
2511: waiting for 2 seconds...
3010: Timeout for 3000
3512: Timeout for 3500
4011: Timeout for 4000
4511: Timeout for 4500
4511: waiting for the rest...
5011: Timeout for 5000
5011: all done
(或大约,取决于事物)。
您可以在那里查看解决超时的顺序。
答案 1 :(得分:1)
当您致电setTimeout
时,您的计时器开始计时,而当您await
履行其诺言时,不是。
运行(res) => setTimeout(res, 2000)
时,您有4个先前的setTimeouts
完成并在解决之前调用console.log
。
答案 2 :(得分:0)
我也偶然发现了这种误解:当您定义Promise时,它的功能即在该时刻执行。如果我了解您要执行的操作,则需要定义一个函数数组,并根据需要调用它们。
(function () {
let val = 0
const promiseArr = []
for (let i = 0; i < 10; i++) {
promiseArr[i] = () => new Promise((res) => {
val += 500
setTimeout((val2) => {
console.log(val2)
res()
}, val, val)
})
}
console.log();
(async function() {
await Promise.all(promiseArr.slice(0, 5).map((fn) => fn()))
console.log('start await')
await new Promise((res) => setTimeout(res, 2000))
console.log('done await')
await Promise.all(promiseArr.slice(6, 10).map((fn) => fn()))
})()
}) ()