在 JavaScript 中实现多个异步任务顺序执行,最推荐的方式是在 async 函数中使用 for...of 循环配合 await 关键字。这种方式适合任务之间存在数据依赖或需要严格顺序的场景,风险在于会阻塞后续代码执行,导致总耗时增加。
先说结论:async/await 串行控制核心在于等待每个 Promise resolve 后再执行下一次循环
- 适合:任务间存在数据依赖或顺序强制要求的场景
- 先看:循环结构必须使用 for...of 或普通 for 循环
- 建议:每个 await 调用外层包裹 try-catch 防止中断
快速处理思路
async function runTasks() {
for (const task of tasks) {
await task();
}
}为什么会这样
await 表达式会暂停 async 函数的执行,直到 Promise settled。
JavaScript 的事件循环机制决定了异步操作需要等待状态变更。await 操作符会让出线程控制权,但保持函数上下文,直到被 await 的 Promise resolved 或 rejected。
分步处理
1. 定义 async 函数:使用 async 关键字声明包含异步逻辑的函数。
2. 准备任务数组:将需要顺序执行的异步函数或 Promise 放入数组。
3. 使用 for 循环:选择 for...of 或传统 for 循环,避免使用 forEach。
4. 内部 await:在循环体内对每个任务调用 await。
5. 错误处理:在循环内部或外部包裹 try-catch 捕获潜在 rejection。
怎么验证是否生效
在任务前后打印时间戳或顺序标识,观察控制台日志是否按预期顺序输出。若后一个任务的日志始终出现在前一个任务完成之后,则串行控制生效。
常见坑
Array.prototype.forEach 不支持 await 等待,会导致所有任务并发启动。未捕获的 Promise rejection 会导致进程退出或静默失败。
常见问题
forEach 循环里能用 await 吗?
不能。forEach 不会等待异步操作完成,会立即执行下一次迭代。
单个任务报错会影响后续任务吗?
会。如果不使用 try-catch 包裹,单个 await 抛出异常会终止整个 async 函数。
串行执行会影响性能吗?
会。总耗时等于各任务耗时之和,比并行执行慢,但能保证顺序。
参考来源
MDN Web Docs: async function - https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function
MDN Web Docs: await - https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/await