gpt4 book ai didi

javascript - 为什么异步函数在 Promise 稍后启动后完成执行?

转载 作者:行者123 更新时间:2023-12-04 13:28:22 25 4
gpt4 key购买 nike

这是我不明白的关于事件循环的事情。
这是代码:

async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}

async function async2() {
console.log('async2 start');
return new Promise((resolve, reject) => {
resolve();
console.log('async2 promise');
})
}

console.log('script start');

setTimeout(function() {
console.log('setTimeout');
}, 0);

async1();

new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
}).then(function() {
console.log('promise3');
});

console.log('script end');

结果是:
script start
async1 start
async2 start
async2 promise
promise1
script end
promise2
promise3
async1 end
setTimeout
我不明白为什么 async1 endpromise 2 之后打印和 promise 3 .
在解释这个的事件循环中会发生什么?这些微任务在队列中以什么顺序推送和弹出?

最佳答案

你很惊讶为什么async1 end紧随其后 promise2promise3 ,尽管它在它们之前被调用,并且微任务是按照它们入队的顺序执行的。
然而,它实际上归结为 async 需要多少个微任务。功能来解决。
看看这个(它是相同的代码,但有 4 个原始 promise ):

async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}

async function async2() {
console.log('async2 start');
return new Promise((resolve, reject) => {
resolve();
console.log('async2 promise');
})
}

console.log('script start');

setTimeout(function() {
console.log('setTimeout');
}, 0);

async1();

new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
}).then(function() {
console.log('promise3');
}).then(function() {
console.log('promise4');
});

console.log('script end');
/* Just to make the console fill the available space */
.as-console-wrapper {
max-height: 100% !important;
}

哎呀, async1 end不再在最后:它在 promise4 之前!
那么这告诉我们什么呢? 这意味着 async1 end在 3 个微任务之后记录(不包括由 promiseN 引起的那些)。
什么需要这 3 个微任务? 让我们检查一下:
最后一个很明显: await运算符(operator)在 async1消耗一个。
我们还剩两个。
要看到,在 async2 ,而不是通过 Promise 创建 promise 构造函数,创建一个 thenable(一个具有 .then() 方法的对象,又名。promise-like 对象),其行为相同(嗯,一个真正的 promise 复杂得多,但对于这个例子,它是这样工作的)。我看起来像这样:

async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}

async function async2() {
console.log('async2 start');

console.log('async2 promise');
return {
then(resolve, reject){
queueMicrotask(() => {
resolve();
console.log('async2 resolve');
});
return Promise.resolve()
}
};
}

console.log('script start');

setTimeout(function() {
console.log('setTimeout');
}, 0);

async1();

new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
}).then(function() {
console.log('promise3');
}).then(function() {
console.log('promise4');
});

console.log('script end');
/* Just to make the console fill the available space */
.as-console-wrapper {
max-height: 100% !important;
}

但是,您可能会发现仍然有问题。 promise2之前仍然被调用 async2 resolve . async函数在 return 之前返回一个 promise声明达成。这是有道理的,但这也意味着,它们不能返回传递给 return 的同一个 promise 对象。 .他们也必须等待返回的 promise !
那么,让我们看看我们的自定义是什么时候 then函数调用:

async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}

async function async2() {
console.log('async2 start');

console.log('async2 promise');
return {
then(resolve, reject){
console.log('async2 then awaited')
queueMicrotask(() => {
resolve();
console.log('async2 resolve');
});
}
};
}

console.log('script start');

setTimeout(function() {
console.log('setTimeout');
}, 0);

async1();

new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
}).then(function() {
console.log('promise3');
}).then(function() {
console.log('promise4');
});

console.log('script end');
/* Just to make the console fill the available space */
.as-console-wrapper {
max-height: 100% !important;
}

啊哈,在一个新的微任务中!

我们找到了所有的漏洞,所以现在我们可以看到 async事物与 promise 交错执行s(这里 --> 表示入队, <-- 表示日志;微任务用 μt 标记):
MACROTASK #0

<-- script start

setTimeout enqueued, but it creates a MACROTASK, so it always comes at last --> MT#1

async1 called
<-- async1 start
async2 called
<-- async2 start
promise executor called synchronously
<-- async2 promise
resolved promise returned to async2
async2 execution halted --> μt#1
async1 execution halted at await

promise executor called synchronously
<-- promise1
promise1 resolved --> μt#2
`then` chain built

<-- script end

microtask #1
async2 continues, calls `then` of the returned promise
<-- async2 `then` awaited
promise's `then` enqueues microtask for calling callback of async2 --> μt#3

microtask #2
promise2 `then` called
<-- promise2
promise2 resolved --> μt#4

microtask #3
called queued callback of promise
<-- async2 resolve
async2 completes
promise returned by async2 resolves --> μt#5

microtask #4
promise3 `then` called
<-- promise3
promise3 resolved --> μt#6

microtask #5
async1 continues
<-- async1 end
async1 completes

microtask #6
promise4 `then` called
<-- promise4
promise4 resolved

MACROTASK #1

timer callback called
<-- setTimeout

关于javascript - 为什么异步函数在 Promise 稍后启动后完成执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66704631/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com