【问题标题】:Async programing in Javascript - Promise.all() do not work as expectedJavascript 中的异步编程 - Promise.all() 无法按预期工作
【发布时间】:2021-04-02 15:29:09
【问题描述】:

我陷入Javascript 中的异步编程。 我知道Promise.all() 会并行运行。

你能告诉我下面这段代码有什么问题吗?

应该是100ms。但实际上,它需要200ms :(

// 1. Define function here
var getFruit = async (name) => {
  const fruits = {
    pineapple: ":pineapple:",
    peach: ":peach:",
    strawberry: ":strawberry:"
  };
  await fetch('https://jsonplaceholder.typicode.com/photos'); // abount 100ms 
  return fruits[name];
};

var makeSmoothie = async () => {
  const a = getFruit('pineapple');
  const b = getFruit('strawberry');
  const smoothie = await Promise.all([a, b]);
  return smoothie;
  //return [a, b];
};
  
/// 2. Execute code here
var tick = Date.now();
var log = (v) => console.log(`${v} \n Elapsed: ${Date.now() - tick}`);
makeSmoothie().then(log);

【问题讨论】:

  • api 返回照片列表,您正在尝试获取水果.. 它们有什么关系?
  • @TangentiallyPerpendicular 不,getFruit 中的 await 不会阻塞 Promise.all 正在调用的并行 getFruit 调用。
  • @Nilesh Patel 我只需要一些承诺来检测Promise.all 是否工作正常。特别是我对getFruit() 方法的错误。

标签: javascript promise async-await es6-promise asynccallback


【解决方案1】:

您的逻辑很好,它从客户端尽可能并行运行。

您可以通过等待 setTimeout 而不是 fetch 来测试:

await new Promise(resolve => setTimeout(resolve, 100));

占位符站点可能在其一侧排队连接或其他原因。无论哪种方式,您都应该使用可预测的东西来衡量,而不是网络。

编辑:

只是为了解释更多不适合评论的内容。

让我们把我的等待技巧变成一个实际的函数:

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

好的,现在您可以将其称为await wait(100)。现在比较一下:

  • await wait(100)
  • await fetch(...)

就您的代码设置而言,它们是相同的。他们正在执行一些需要大约 100 毫秒并返回的异步任务。如果Promise.all() 没有并行运行,wait(100) 版本肯定需要 200 毫秒或更长时间。

fetch 的测试不如setTimeout 可靠,因为它是通过网络运行的。这个调用有很多你无法控制的事情,比如:

  • 某些浏览器会限制与同一域建立的并行连接数
  • DNS 或服务器本身滞后,典型的网络故障
  • 域本身可能会强制从您的 IP 一次连接 1 个

目前尚不清楚究竟是什么导致了这里明显的同步行为。也许您会在网络面板中找到一些答案。但就代码而言,您无事可做。可证明它与 setTimeout 测试并行化,因为它只是一个本地计时器,因此作为测试更可靠。

【讨论】:

  • 嗨兄弟,你能告诉我为什么我的 fetch() 不能并行运行吗?你的fetch()await new Promise有什么区别?
  • @Phong 他已经告诉过你为什么你的 fetch 不能并行运行。 Fetch 可以并行运行,但他猜测https://jsonplaceholder.typicode.com 正在按顺序处理请求。为什么jsonplaceholder.typicode.com 没有并行响应可能是由于很多原因:所有浏览器对每个 IP 地址都有一个连接限制,因此您可能会达到该限制(请记住,浏览器请求有时会生成两个请求 - CORS 的 OPTION 请求然后是真正的 GET 请求,可以是两个连接),网站本身可能有有限的带宽等。
  • 要尝试的一件事是请求 100 个图像而不是 2 个。一些服务器和路由器在响应大量数据时会增加带宽分配。为什么有些网络设备和服务器是这样设计的?因此,他们可以平等地为多个客户提供服务,而不是快速为单个客户提供服务
  • 感谢@slebetman 和@Matt。解决了。顺便说一句,如果我像loop from 1 to 2000 这样的代码阻止程序更改await fetch()await wait(100) 会发生什么。这会变得同步,对吗?结果,Promise.all() 不能并行工作?
  • @Phong 正确,Promise.all 只能并行调度异步任务。它不能将同步 CPU 循环转换为单独的线程或任何东西。 fetch 自然是异步的,这就是为什么它可以被 Promise.all 调度
猜你喜欢
  • 2014-12-06
  • 2017-08-28
  • 2017-04-17
  • 2023-03-03
  • 2016-10-13
  • 1970-01-01
  • 2019-12-29
  • 2017-12-23
相关资源
最近更新 更多