我试图弄清楚为什么 Promise 在
for...of
与 map()
中的工作方式似乎有所不同。
data
是 {app: MY_APP, link: MY_LINK}
形式的对象数组。我正在尝试将其转换为 {app: MY_APP, status: true OR false}}
的形式。函数 checkLink()
是异步的,因为它使用 node-fetch
并基本上返回给定链接是否为 200。使用 for...of
,我得到了所需的对象:
let objToSend = [];
for (obj of data) {
objToSend.push({ app: obj.app, status: await checkLink(obj.link) });
}
// returns [{app: MY_APP, status: true}, ...]
但是使用
map
,如下所示,我得到了一组待处理的承诺。任何帮助将不胜感激:
let objToSend = data.map(async obj => {
return {
app: obj.app,
status: await checkLink(obj.link)
};
});
// returns [ Promise { <pending> }, ...]
我还尝试在
Promise.all(objToSend)
代码之后执行 map
,但它反而返回 Promise { <pending> }
我将把解释留给其他答案,但只是想指出,也存在性能差异。
您的第一个解决方案会在每次迭代中等待承诺的解决,只有在前一个解决方案已解决时才调用
checkLink
。这是一个顺序解决方案。
check link1 => wait => check link2 => wait => check link3 => wait
第二种解决方案迭代每个元素并发出请求,而不等待 Promise 解决;因此,返回了一组承诺。如果您等待所有承诺都得到解决,您会发现此解决方案要快得多,因为请求是并行发送的。
check link1 => check link2 => check link3 => wait for all
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
async function checkLink(link) {
await sleep(Math.random() * 1000 + 500); // sleep between 500 and 1500 ms
console.log(link);
return `status #${link}`;
}
(async function () {
const data = new Array(5).fill().map((_, index) => ({ app: "app", link: index }));
let objToSend;
console.log("solution #1");
objToSend = [];
for (let obj of data) {
objToSend.push({ app: obj.app, status: await checkLink(obj.link) });
}
console.log(objToSend);
console.log("==============================================");
console.log("solution #2");
objToSend = await Promise.all(data.map(async obj => {
return {
app: obj.app,
status: await checkLink(obj.link)
};
}));
console.log(objToSend);
})();
在代码片段中,第一个解决方案需要 2500 到 7500 毫秒之间的时间,而第二个解决方案需要 500 到 1500 毫秒之间的时间(取决于解析的最慢值)。
(async()=>{
let objToSend = await Promise.all(data.map(async obj => {
return {
app: obj.app,
status: await checkLink(obj.link)
};
}));
console.log(objToSend) //[{app: MY_APP, status: true}, ...]
})()
始终会停止其所在的
await
的执行,在这两种情况下它的工作方式没有不同。然而,在后面的示例中,您确实调用了一些 async function
,并且这些调用将评估为承诺,而在第一个示例中,所有这些 async function
都位于相同的 await
中。我也尝试在地图代码之后执行
async function
,但它反而返回
是的,Promise.all(objToSend)
Promise { <pending> }
,您会得到一系列结果。