同步异步混乱?教你用Promise在循环中保持序列执行
2023-12-06 03:32:33
前言
在前端开发中,我们经常需要在循环中执行异步任务。例如,我们需要从服务器端获取数据,然后根据这些数据渲染页面。如果这些异步任务是相互依赖的,那么我们就需要确保它们按照正确的顺序执行。否则,可能会导致数据不一致或页面渲染错误。
解决方案
1. for+async/await
for+async/await是一种非常简单的方法,它使用async/await语法来在循环中串行执行promise。
async function main() {
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(new Promise((resolve) => {
setTimeout(() => {
resolve(i);
}, 1000);
}));
}
for await (const result of promises) {
console.log(result);
}
}
main();
这种方法非常直观,也很容易理解。但是,它也有一个缺点,那就是它不能处理错误。如果其中一个promise被拒绝了,那么整个循环都会被中断。
2. Array.prototype.reduce+async/await
Array.prototype.reduce+async/await是一种更健壮的方法,它可以使用async/await语法来在循环中串行执行promise,并且可以处理错误。
async function main() {
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(new Promise((resolve) => {
setTimeout(() => {
resolve(i);
}, 1000);
}));
}
const results = await Promise.all(promises);
results.forEach((result) => {
console.log(result);
});
}
main();
这种方法使用Promise.all()方法来等待所有promise都执行完毕。如果其中一个promise被拒绝了,那么Promise.all()方法会将这个promise的错误传递给reduce方法。reduce方法可以使用try/catch语句来捕获这个错误,并继续执行循环。
3. Arr.allSettled+async/await
Arr.allSettled+async/await是一种最健壮的方法,它可以使用async/await语法来在循环中串行执行promise,并且可以处理错误。
async function main() {
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(new Promise((resolve) => {
setTimeout(() => {
resolve(i);
}, 1000);
}));
}
const results = await Promise.allSettled(promises);
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log(result.value);
} else {
console.error(result.reason);
}
});
}
main();
这种方法使用Promise.allSettled()方法来等待所有promise都执行完毕。Promise.allSettled()方法会返回一个数组,其中包含所有promise的结果。如果其中一个promise被拒绝了,那么Promise.allSettled()方法会将这个promise的结果状态设置为"rejected"。我们可以使用forEach方法来遍历这个数组,并根据promise的结果状态来决定如何处理结果。
比较
方法 | 优点 | 缺点 |
---|---|---|
for+async/await | 简单,易于理解 | 不能处理错误 |
Array.prototype.reduce+async/await | 可以处理错误 | 稍微复杂一些 |
Arr.allSettled+async/await | 最健壮,可以处理错误 | 最复杂 |
结论
在循环中串行执行promise有几种不同的方法。每种方法都有其优缺点。在选择方法时,您需要考虑您的具体需求。如果您需要一种简单、易于理解的方法,那么您可以使用for+async/await方法。如果您需要一种可以处理错误的方法,那么您可以使用Array.prototype.reduce+async/await方法或Arr.allSettled+async/await方法。