文章

使用 Promise.all + fetch 在控制台快速验证并发请求

使用 Promise.all + fetch 在控制台快速验证并发请求

在前端调试或接口联调阶段,我们经常会遇到这样的问题:

多个接口是否真的并发执行? 某个接口变慢 / 报错,是否会影响其他请求?

浏览器控制台其实是一个非常适合做并发测试的地方。本文通过一个极简、实用的 Promise.all + fetch 模式,来系统梳理如何正确地在控制台验证并发请求行为。


一、最核心的并发测试写法

推荐的标准写法如下:

1
2
3
4
5
6
7
8
9
10
11
const [resA, resB] = await Promise.all([
  fetch('/api/a'),
  fetch('/api/b')
]);

const [dataA, dataB] = await Promise.all([
  resA.json(),
  resB.json()
]);

console.log(dataA, dataB);

这一段代码非常适合直接粘到 DevTools 控制台中执行,用于快速验证多个接口的并发行为。


二、这段代码到底做了什么?

我们可以把它拆成两个阶段来看。

1️⃣ 第一阶段:并发发起请求(I/O 并发)

1
2
3
4
await Promise.all([
  fetch('/api/a'),
  fetch('/api/b')
]);

这一行的关键点是:

  • 两个 fetch 同时创建并立即发起请求
  • 不存在“等 A 完成再请求 B”的情况
  • 网络面板中可以看到两个请求几乎同时进入 Pending 状态

⚠️ 对比一个常见的“伪并发”写法:

1
2
await fetch('/api/a');
await fetch('/api/b');

上面的代码是严格串行的,只能用于顺序依赖场景,不适合做并发验证。


2️⃣ 第二阶段:并发解析响应体(CPU / 内存阶段)

1
2
3
4
await Promise.all([
  resA.json(),
  resB.json()
]);

这一点经常被忽略,但非常重要:

  • response.json() 本身也是异步操作
  • 如果接口返回体较大,JSON 解析也可能成为性能瓶颈
  • 同样可以(也应该)并发处理

通过拆成两个 Promise.all,可以清晰地区分:

阶段并发内容
第一段网络请求并发
第二段响应解析并发

这在性能分析和问题定位时非常有价值。


三、为什么这种写法特别适合“并发测试”?

✅ 1. 语义非常清晰

  • 并发点非常明确
  • 没有隐藏的 await
  • 一眼就能看出是否存在串行逻辑

✅ 2. 非常适合控制台快速验证

特点包括:

  • 不依赖框架
  • 不依赖构建
  • 不需要额外封装
  • 复制即用

在排查:

  • 后端接口性能
  • 网关限流
  • 并发冲突
  • 请求是否被浏览器阻塞

这些问题时,效率极高。


✅ 3. 与 Network 面板高度契合

配合 Chrome DevTools → Network:

  • 可以直观看到请求是否“同时 Pending”
  • 可以判断是否被 CORS / HTTPS / Mixed Content 拦截
  • 可以对比并发 vs 串行的耗时差异

这是后端 / 前端联调时非常好用的一种方式。


四、需要注意的一个“坑”:Promise.all 的失败行为

Promise.all 有一个非常重要的特性:

只要其中一个 Promise 失败,整体立即 reject

例如:

  • /api/a 成功返回
  • /api/b 网络失败(Failed to fetch)

结果是:

  • A 实际已经请求成功
  • 但整体代码直接抛异常

如果你的测试目标是:

“看看哪些成功,哪些失败”

那么可以使用:

1
2
3
4
5
6
const results = await Promise.allSettled([
  fetch('/api/a'),
  fetch('/api/b')
]);

console.log(results);

这在排查并发异常场景时尤其有用。


五、适用场景总结

这种写法非常适合用于:

  • 并发接口测试
  • 接口性能对比
  • 验证是否被浏览器层拦截
  • 调试后端限流 / 并发控制
  • 博客或技术分享中的示例代码

同时,它也完全可以迁移到实际业务代码中使用。


六、一句话总结

在控制台中验证并发请求,最清晰、最可靠的方式,就是:

await Promise.all([ fetchA, fetchB ])

结构清晰、行为确定、调试友好,非常值得作为一个“并发测试模板”长期保留。

本文由作者按照 CC BY 4.0 进行授权