【问题标题】:.map async callback and event loop.map 异步回调和事件循环
【发布时间】:2019-12-06 20:37:32
【问题描述】:

这段代码sn-p取自google developers

// map some URLs to json-promises
const jsonPromises = urls.map(async url => {
  const response = await fetch(url);
  return response.json();
});

我知道最后 jsonPromises 将是一个 Promise 数组。但是,我不完全确定这是怎么发生的。

根据我的理解,当执行到const response = await fetch(url); 这一行时,它会将其从调用堆栈移动到Web Api,对return response.json(); 执行相同的操作,并从urls 移动到下一个url。这是正确的吗 ?当涉及到简单的 setTimeout 时,我了解事件循环是如何工作的,但是这个例子让我很困惑。

【问题讨论】:

  • 是的,有点。 ...
  • @JonasWilms 你能否逐步解释一下会发生什么来消除我的疑虑?
  • 嘿@Noob,因为 Array.map() 不是异步函数,它不会等待它运行一个元素的每个异步回调完成,然后再在下一个元素上运行它。至于reponse.json(),它只返回一个包装响应对象的解析体的promise。希望能把事情弄清楚一点?在此处获取更多信息:developers.google.com/web/updates/2015/03/introduction-to-fetch
  • @adamz4008 当然,我同意你的看法。我明白你在说什么,我的问题是它是如何与事件循环相关的。您的评论没有回答这个问题。

标签: javascript


【解决方案1】:

会发生什么:

1) .map 函数运行,并为每个元素执行回调(异步函数)。该函数调用fetch,它启动了引擎内部的一些底层魔法。 fetch 返回一个 Promise。到达await,这会停止函数的执行。 .map 对函数的调用评估为一个承诺。 .map 收集所有这些承诺并将它们存储在一个数组中并返回该数组。

2) 有时,在后台运行的其中一个获取已建立连接,并回调 JS 并解析 fetch 承诺。这会导致async function 调用继续进行。 res.json() 被调用,这会导致引擎从连接中收集所有数据包,并将其解析为引擎盖下的 JSON。这再次返回一个 Promise,它得到 awaited,这会导致执行再次停止。

3) 某个时候,其中一个连接结束,整个响应以 JSON 形式提供。承诺解决,async function 调用继续执行,returns,这导致承诺(数组中的那个)被解决。

【讨论】:

  • 对不起,我还在处理你的回答。我对这部分有点困惑。 The call to the function done by .map evaluates to a promise. 我理解 The await gets reached, which halts the functions execution.,但是为什么之后它的评估结果是一个承诺?
  • 它还应该评估什么? return 尚未到达。在那个时间点,我们只知道函数会在未来返回一些东西。它承诺会这样做。
【解决方案2】:

由于异步函数返回一个 Promise,因此可以将该示例视为任何其他返回 Promise 的函数:

// map happens synchronously and doesn't wait for anything
const map = (arr, cb) => {
  const mapped = [];
  for (const [i, element] of arr.entries()) {
    mapped.push(cb(element))
  }
  return mapped;
}

// just return a promise that resolves in 5 seconds with the uppercased string
const promiseFn = url => {
  return new Promise(resolve => setTimeout(() => resolve(url.toUpperCase()), 5000))
}

const promiseArray = map(['url', 'url', 'url'], promiseFn)

异步回调返回的所有承诺都是同步推送的。它们的状态是异步修改的。

另一方面,如果您正在寻找 setTimeout 和 Promise 与事件循环之间的区别,请在此处查看接受的答案:What is the relationship between event loop and Promise

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-08
    • 2017-07-07
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多