`Promise.all` 是否受到浏览器施加的并发连接限制?

Does `Promise.all` suffer from the limit of concurrent connections imposed by the browser?

假设 api 服务器正在使用 HTTP/1.1,并且浏览器限制每个域 6 个并发 TCP 连接。 这是否意味着如果我用 Promise.all 一次调用 7 api 那么最后一个 api 将不得不等待第一个 api 的请求通过网络返回?

Promise.all([api(), api(), api(), api(), api(), api(), api()]) // 7 api calls

HTTP/2 是否也通过多路复用解决了这个问题,其中所有这些 API 调用都将在同一个连接上,因此它们不需要等待任何东西?

是的,但这不是 Promise.all 特有的限制。一般来说,像

这样的表达式
anotherFn([fn(), fn(), fn()])

相当于做

const r1 = fn();
const r2 = fn();
const r3 = fn();
anotherFn([r1, r2, r3]);

参数列表中的所有内容都会在结果传递之前进行评估。如果评估所有内容的过程进行了一堆 API 调用,则另一个函数 - Promise.allanotherFn 不可能对此做任何事情,因为这些发生在函数运行之前。

then the last api will have to wait for the first api's request to come back over the network?

如果我们可以假设限制如您所说 - 浏览器一次只能连接 6 个 API - 那么是的。

是的,HTTP/2 在这些情况下很有用,因为每个域只需要一个连接,并且可以通过该连接发送多个请求,而无需 运行 进入浏览器连接限制。

Does that mean if I do 7 api calls at once with Promise.all then the last api will have to wait for the first api's request to come back over the network?

是的,确实如此。

您的 Promise.all([api(), api(), ...]) 语句将立即 运行 所有 api() 函数调用。这将导致前 6 个请求被发送,第 7 个请求将排队直到前 6 个请求之一完成,在这种情况下浏览器将发送第 7 个。

此行为实际上与 Promise.all() 没有任何关系。如果您只是这样做,则会发生相同的行为:

const promises = [api(), api(), api(), api(), api(), api(), api()];

即使只使用该语句,第 7 个 http 请求也不会发送到主机,直到前 6 个中的一个请求完成。完全是因为浏览器对同一主机的连接限制。

仅供参考,Promise.all() 仍然有效,所有 api 请求仍然有效,只是需要等待更长的时间才能完成所有请求,而不是你没有点击连接限制。