imh*_*rn1 6 javascript asynchronous for-loop promise async-await
(英语不是我的母语,所以如果您发现任何英语,请提前原谅我的英语)
此时,我对 Promises 和 Async wait 函数非常满意,我也知道如何使用 Promise.all (它只是等待内部的所有承诺首先解析,然后从所有承诺中提取值,然后返回一个数组将 .then 函数与这些值一起使用。)
现在我想知道 for wait 在幕后是如何工作的。
我刚刚写了这段代码:
async function f() {
let p1 = new Promise(function (r) {
setTimeout(r, 3000, 1)
})
let p2 = new Promise(function (r) {
setTimeout(r, 2000, 2)
})
let p3 = new Promise(function (r) {
setTimeout(r, 1000, 3)
})
let arrayOfPromises = [p1, p2, p3];
for await (let p of arrayOfPromises) {
let data = await p;
console.log(data)
}
}
f();Run Code Online (Sandbox Code Playgroud)
现在我的问题是,当它命中第一次迭代时会发生什么,它将命中await关键字,并且await立即返回一个待处理的承诺,那么下面的代码在技术上是否在每次迭代中评估为待处理的承诺?
{
let data = await p;
console.log(data)
}
Run Code Online (Sandbox Code Playgroud)
所以我很困惑到底发生了什么,对于第一次迭代,setTimeout 将注册 3 秒,第二次注册 2 秒,第一次注册 1 秒。由于我们没有同步代码,所以所有回调将一个接一个地运行,p3 将首先被解析,然后是 p2,最后是 p1!
现在直觉上我认为一旦 p1、p2、p3 被解析,这段代码“console.log(data)”就会被放入微任务队列中,并且由于我们的 p3 首先被解析,所以我们应该得到 3, 2, 1 但我们'得到 1、2、3,那么我的理解还缺少什么?
(显然代码没有放入微任务队列中,它的函数可能会像生成器函数一样执行 .next() 之类的操作,但我认为这并不重要)
似乎在 for wait of 中,第一个 Promise 将首先被记录,无论它与迭代中的其他 Promise 相比解决得有多快或多晚,那么到底发生了什么?
这是一个可以按您的预期工作的代码:
async function printWhenResolved(p) {
const data = await p; console.log(data)
}
function createIteratorsAndBindPrinting() {
let p1 = new Promise(function (r) {
setTimeout(r, 3000, 1)
})
let p2 = new Promise(function (r) {
setTimeout(r, 2000, 2)
})
let p3 = new Promise(function (r) {
setTimeout(r, 1000, 3)
})
let arrayOfPromises = [p1, p2, p3];
for (let p of arrayOfPromises) {
printWhenResolved(p)
}
console.log('end of createIteratorsAndBindPrinting')
}
createIteratorsAndBindPrinting()
Run Code Online (Sandbox Code Playgroud)
现在,从语义上讲,我认为处理看起来很清楚。在“for await (... of ...)”上,迭代一个可迭代对象,在每个点都根据迭代的当前值是同步还是异步提供其值来做出决定。如果它同步提供它的值,我们立即执行“for”中的代码块。如果它异步提供值,我们会等到提供值,然后调用“for”中的块。
因此,我们依次等待每个可迭代对象 - 然后才离开for- 块。
在我提供的代码中,我们对每个 Promise 调用一个异步函数,当它解析时,会将值记录到控制台。这也是为什么你let data = await p是多余的(因为你的await也在-construct中for)。
通过这种方式,async函数是一种组织反应式代码(即调用过程并带有例如 Promise 解析的代码)的方法,而无需回调地狱或 then 链接。这可以说允许更多的模块化、表现力和可测试性。另请参阅/sf/answers/3814797031/
要查看代码具体执行的操作的差异(没有冗余),请将上面的代码与以下代码进行比较:
async function createIteratorsAwaitAndPrint() {
let p1 = new Promise(function (r) {
setTimeout(r, 3000, 1)
})
let p2 = new Promise(function (r) {
setTimeout(r, 2000, 2)
})
let p3 = new Promise(function (r) {
setTimeout(r, 1000, 3)
})
let arrayOfPromises = [p1, p2, p3];
for await (let p of arrayOfPromises) {
console.log(p)
}
console.log('end of createIteratorsAwaitAndPrint')
}
createIteratorsAwaitAndPrint()
Run Code Online (Sandbox Code Playgroud)
await这里我们在 for 构造中进行。请注意,“end of [...]”日志在我们完成迭代之前不会发生。
| 归档时间: |
|
| 查看次数: |
2875 次 |
| 最近记录: |