此代码片段取自 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 会await
ed,这会导致执行再次停止。
3(在某个时候,其中一个连接结束,整个响应以JSON形式提供。承诺解析,async function
调用继续执行,return
s,这会导致承诺(数组中的那个(被解析。
由于异步函数返回一个承诺,因此可以将该示例视为任何其他承诺返回函数:
// 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 之间的关系是什么