.map 异步回调和事件循环



此代码片段取自 google 开发者:

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

我知道最后jsonPromises将是一系列的承诺。但是,我不完全确定这是如何发生的。

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

以下是发生的情况:

1(.map函数运行,并执行每个元素的回调(异步函数(。该函数调用fetch,启动引擎引擎内部的一些引擎盖下的魔法。fetch返回一个承诺。到达await,这将停止函数执行。.map完成的对函数的调用计算结果为承诺。.map收集所有这些承诺并将它们存储在数组中并返回数组。

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

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

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

// 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 相对于事件循环之间的区别,请在此处检查接受的答案:事件循环和 Promise 之间的关系是什么

最新更新