JavaScript异步调度中,串行用for...of+await逐个执行,保证顺序与错误处理;并行用Promise.all同时发起所有任务;可控并发则通过分批+Promise.all实现最大数量限制。

JavaScript 中异步函数的串行和并行调度,核心在于控制 Promise 的执行时机与依赖关系。串行即一个接一个执行,前一个完成才开始下一个;并行即多个同时发起,不互相等待。两者都无需第三方库,用原生 Promise 和 async/await 即可清晰实现。
串行执行:用 for...of + await 逐个等待
最直观、最易维护的方式是用 async 函数配合 for...of 循环,每次 await 当前异步操作完成后再进入下一轮。它天然保证顺序,也便于错误处理和中途退出。
示例:
async function runSerial(tasks) {
const results = [];
for (const task of tasks) {
try {
const res = await task();
results.push(res);
} catch (err) {
console.error('任务失败,停止串行', err);
break; // 或 continue 跳过当前任务
}
}
return results;
}
// 使用
const tasks = [
() => fetch('/api/a').then(r => r.json()),
() => fetch('/api/b').then(r => r.json()),
() => fetch('/api/c').then(r => r.json())
];
runSerial(tasks);
并行执行:用 Promise.all 同时触发所有任务
Promise.all 是并行的标准解法——所有 Promise 立即启动,返回一个等待全部完成的 Promise。注意:任一失败则整体拒绝(除非你包装成 always-resolve)。
立即学习“Java免费学习笔记(深入)”;
常见写法:
- 直接传入 Promise 数组:
Promise.all([p1(), p2(), p3()]) - 若任务是函数,先映射调用:
Promise.all(tasks.map(t => t())) - 需要容错?用
Promise.allSettled替代,它总成功,返回每个任务的 {status, value/reason}
进阶:可控并发(如最多同时跑 3 个请求)
既不是完全串行,也不是全量并行,而是限制最大并发数。可用“滑动窗口”思路实现:
- 维护一个运行中的 Promise 集合(如数组)
- 每次 push 一个新任务,并监听其完成;完成一个就从集合中移除
- 当数量
更简洁的做法是使用 Promise.all 分批 + 递归或 reduce:
async function runLimited(tasks, limit = 3) {
const results = [];
for (let i = 0; i < tasks.length; i += limit) {
const batch = tasks.slice(i, i + limit).map(t => t());
const batchResults = await Promise.all(batch);
results.push(...batchResults);
}
return results;
}
别踩坑:避免常见误解
以下写法看似并行,实为串行:
// ❌ 错误:await 写在循环内 → 仍是串行
for (const task of tasks) {
await task(); // 每次都等完才进下一次
}
// ✅ 正确:先生成 Promise,再统一 await
const promises = tasks.map(t => t());
await Promise.all(promises);
另外,Promise.all 不等于“同时开始”——它只是不阻塞后续代码,但所有 Promise 构造器本身是同步执行的(比如 fetch() 调用会立刻发请求),所以确实是并行发起网络请求。


















