使用 async/await
结合 for...of
循环
- 代码示例:
async function processIterable(iterable) {
for (const item of iterable) {
try {
const result = await asyncOperation(item);
console.log(result);
} catch (error) {
console.error(error);
}
}
}
function asyncOperation(item) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve(`Processed ${item}`);
} else {
reject(new Error(`Error processing ${item}`));
}
}, 100);
});
}
const iterable = [1, 2, 3, 4, 5];
processIterable(iterable);
- 优点:
- 代码结构清晰,类似于同步代码,可读性强,有效避免回调地狱。
- 可以方便地使用
try...catch
进行错误处理,使得错误处理更直观。
- 缺点:
- 由于
await
会暂停函数执行,直到Promise被解决,所以异步操作是顺序执行的。如果异步操作之间没有依赖关系,这种方式可能会导致性能问题,因为没有充分利用并行处理的优势。
使用 Promise.all
- 代码示例:
function processIterable(iterable) {
const promises = iterable.map(async item => {
try {
return await asyncOperation(item);
} catch (error) {
return error;
}
});
return Promise.all(promises);
}
function asyncOperation(item) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve(`Processed ${item}`);
} else {
reject(new Error(`Error processing ${item}`));
}
}, 100);
});
}
const iterable = [1, 2, 3, 4, 5];
processIterable(iterable).then(results => {
console.log(results);
}).catch(error => {
console.error(error);
});
- 优点:
- 所有异步操作并行执行,大大提高了整体的执行效率,适合异步操作之间没有依赖关系的场景。
- 可以通过
Promise.all
返回的Promise统一处理所有操作的结果或错误。
- 缺点:
- 如果其中一个Promise被拒绝,
Promise.all
会立即拒绝,即使其他Promise可能还在执行。这可能导致部分操作白执行,在某些场景下不是期望的行为。
- 错误处理相对
async/await
的 try...catch
不够直观,需要通过 .catch
来捕获整个 Promise.all
的错误。
使用 Promise.allSettled
- 代码示例:
function processIterable(iterable) {
const promises = iterable.map(async item => {
try {
return await asyncOperation(item);
} catch (error) {
return error;
}
});
return Promise.allSettled(promises);
}
function asyncOperation(item) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve(`Processed ${item}`);
} else {
reject(new Error(`Error processing ${item}`));
}
}, 100);
});
}
const iterable = [1, 2, 3, 4, 5];
processIterable(iterable).then(results => {
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log(result.value);
} else {
console.error(result.reason);
}
});
});
- 优点:
- 所有异步操作并行执行,提高效率。
- 无论每个Promise是成功还是失败,
Promise.allSettled
都会等到所有Promise都完成,并返回一个包含每个Promise结果的数组,便于统一处理所有操作的结果,即使部分操作失败也不会影响其他操作的继续执行和结果收集。
- 缺点:
- 代码复杂度相对较高,需要遍历结果数组分别处理成功和失败的情况。
- 相较于
Promise.all
,如果所有操作都成功,Promise.allSettled
会多一些不必要的处理,因为它要等待所有操作完成并构建结果数组。