返回
巧用async/await,告别forEach异步烦恼
前端
2023-12-20 06:52:51
在繁忙的JavaScript世界中,异步编程已成为一种常态,它允许我们在不阻塞主线程的情况下执行耗时的操作。然而,当涉及到遍历数组并针对每个元素执行异步任务时,我们经常会遇到一些挑战。
在这种情况下,forEach 方法似乎是一个显而易见的选择,因为它提供了一种简单的方法来遍历数组。但是,当我们将await 引入forEach 时,事情就开始变得复杂起来。
await 在forEach 中无效
场景 :现有一个数组,要依次循环去请求拿到结果。
错误示例 :
const asyncForEach = async (array, callback) => {
array.forEach(async (item) => {
const result = await callback(item);
console.log(result);
});
};
通过控制台发现,代码并没有按照预期依次打印出来,而是等待一下,全部打印出来。
问题根源 :
forEach 本身是一个同步方法,它将依次调用回调函数。然而,当我们在回调函数中使用await 时,forEach 会立即执行所有回调,并等待所有异步任务完成后才继续执行。
解决方案:
为了解决此问题,我们可以使用async/await 与for...of 循环的组合:
const asyncForEach = async (array, callback) => {
for (const item of array) {
const result = await callback(item);
console.log(result);
}
};
for...of 循环是一个异步迭代器,它会等待每个await 操作完成,然后再继续执行。这样,asyncForEach 函数将依次执行每个异步任务,并立即打印结果。
其他技巧 :
1. 控制并发
通过限制并发请求的数量,我们可以优化性能并防止服务器过载。例如:
const asyncForEach = async (array, callback, limit = 5) => {
const requests = [];
for (const item of array) {
requests.push(callback(item));
}
await Promise.all(requests.slice(0, limit));
return await Promise.all(requests.slice(limit));
};
2. 错误处理
在异步操作中处理错误至关重要。我们可以使用try...catch 块或Promise.catch() 来捕获错误并防止应用程序崩溃。
总结
通过巧妙地使用async/await 和for...of 循环,我们可以克服forEach 中await 的限制,从而有效地实现异步遍历。记住,理解异步编程的原理并正确使用这些工具,对于构建响应迅速且可靠的JavaScript应用程序至关重要。