[英]What is happening with this chain of Promises?
I am scratching my head trying to understand what is happening with the following cases.我正在挠头试图了解以下情况发生了什么。
Case 1:情况1:
async function doSomething(): Promise<void> {
return new Promise(resolve => {
const promise = (async () => "A")();
promise
.then(() => {
console.log("THEN");
resolve();
})
.catch(() => {
console.log("CATCH");
})
.finally(() => {
console.log("FINALLY");
});
});
}
async function main() {
await doSomething();
console.log("DONE");
}
main().catch(console.error);
Output, as expected: Output,符合预期:
THEN
FINALLY
DONE
But in case 2:但在情况 2 中:
async function doSomething(): Promise<void> {
return new Promise(resolve => {
const promise = (async () => Promise.resolve("A"))();
promise
.then(() => {
console.log("THEN");
resolve();
})
.catch(() => {
console.log("CATCH");
})
.finally(() => {
console.log("FINALLY");
});
});
}
async function main() {
await doSomething();
console.log("DONE");
}
main().catch(console.error);
The output is: output 是:
THEN
DONE
FINALLY
And case 3:案例 3:
async function doSomething(): Promise<void> {
return new Promise(resolve => {
const promise = (async () => Promise.resolve("A"))();
promise
.then(() => {
console.log("THEN");
resolve();
})
.finally(() => {
console.log("FINALLY");
});
});
}
async function main() {
await doSomething();
console.log("DONE");
}
main().catch(console.error);
The output is: output 是:
THEN
FINALLY
DONE
What is happening exactly to the chain of promises?承诺链到底发生了什么?
Why the case 2 doesn't print "THEN, FINALLY, DONE"?为什么案例 2 不打印“THEN, FINALLY, DONE”?
Why the case 3 behaves differently from case 2?为什么案例 3 的行为与案例 2 不同?
I might have understood what happened with the 3 cases.我可能已经明白这 3 个案例发生了什么。
The difference in number of promises and the resolution of promises with promise changes the sequence of microtask enqueued causing the difference in print statements. promise 的承诺数量和承诺解决方案的差异改变了微任务排队的顺序,导致打印语句的差异。
First of all lets try to simplify the code removing the async/await.首先让我们尝试简化删除异步/等待的代码。 I will use the code of case 1 for the simplification.
我将使用案例 1 的代码进行简化。
The main block主块
async function doSomething(): Promise<void> {
return new Promise(resolve => {
...
});
}
async function main() {
await doSomething();
console.log("DONE");
}
main().catch(console.error);
can be rewrote to:可以重写为:
function doSomething(): Promise<void> {
// Promise A
return new Promise(resolve => {
// Promise B
const b = new Promise(resolve => {
...
});
resolve(b);
});
}
doSomething()
.then(function externalThen() {
console.log("DONE");
});
The promise
declaration for case 1:案例1的
promise
申报表:
const promise = (async () => "A")();
becomes:变成:
const promise = Promise.resolve("A");
and for case 2 and 3:对于案例 2 和案例 3:
const promise = (async () => Promise.resolve("A"))();
becomes:变成:
const promise = new Promise(resolve => {
resolve(Promise.resolve("A"))
});
Putting all together and removing unnecessary functions and variable declarations:将所有内容放在一起并删除不必要的函数和变量声明:
// Promise A
new Promise(resolve => {
// Promise B
const b = new Promise<void>(resolve => {
// Promise C
new Promise(resolve => {
resolve("A");
})
.then(function then1() {
console.log("THEN");
resolve();
})
.catch(function catch1() {
console.log("CATCH");
})
.finally(function finally1() {
console.log("FINALLY");
});
});
resolve(b);
})
.then(function externalThen() {
console.log("DONE");
});
For case 2 and 3 the Promise C declaration becomes:对于案例 2 和案例 3,Promise C 声明变为:
// Promise C
new Promise(resolve => {
// Promise D
resolve(Promise.resolve("A"));
})
then
, catch
and finally
methods are executed as microtask when the promise fulffils.then
、 catch
和finally
方法的回调将作为微任务执行。p1
to the resolve
callback of a Promise p2
generates a new microtask that chains p1
to p2
.p1
传递给 Promise p2
的resolve
回调会生成一个将p1
链接到p2
的新微任务。 The then
method of p1
is called passing the resolve
and reject
callbacks of p2
.p1
的then
方法传递p2
的resolve
和reject
回调。// Promise A
new Promise(resolve => {
// Promise B
const b = new Promise<void>(resolve => {
// Promise C
new Promise(resolve => {
resolve("A");
})
.then(function then1() {
console.log("THEN");
resolve();
})
.catch(function catch1() {
console.log("CATCH");
})
.finally(function finally1() {
console.log("FINALLY");
});
});
resolve(b);
})
.then(function externalThen() {
console.log("DONE");
});
then1
is added in the microtask queue then1
的执行被添加到微任务队列中resolve(b)
resolve(b)
b
is a Promise that is passed as resolve value for Promise A. This generates a new microtask that chains B to A. b
是一个 Promise,作为 Promise A 的解析值传递。这会生成一个新的微任务,将 B 链接到 A。then1
, chain-B-to-A
.then1
, chain-B-to-A
。then1
: then1
的执行:
b
b
then
resolves and enqueues a microtask for catch1
then
生成的 Promise 为catch1
解析并入队一个微任务chain-B-to-A
: chain-B-to-A
执行:
b.then(a.resolve, a.reject)
b.then(a.resolve, a.reject)
then-BA
is enqueued then-BA
已入队catch
, then-BA
catch
, then-BA
catch1
: catch1
的执行:
finally1
finally1
一个微任务then-BA
: then-BA
的执行:
externalThen
externalThen
解析并入队一个微任务finally1
, externalThen
finally1
, externalThen
finally1
: prints "FINALLY" finally1
的执行:打印“FINALLY”externalThen
: prints "DONE" externalThen
的执行:打印“DONE”// Promise A
new Promise(resolve => {
// Promise B
const b = new Promise<void>(resolve => {
// Promise C
new Promise(resolve => {
// Promise D
resolve(Promise.resolve("A"));
})
.then(function then1() {
console.log("THEN");
resolve();
})
.catch(function catch1() {
console.log("CATCH");
})
.finally(function finally1() {
console.log("FINALLY");
});
});
resolve(b);
})
.then(function externalThen() {
console.log("DONE");
});
execution traverse the Promise constructors for Promise A, B and C执行遍历 Promise 构造函数 Promise A, B 和 C
Promise C is resolved with Promise D, this generates a microtask to chain D to C Promise C 解析为 Promise D,这会生成一个微任务将 D 链接到 C
execution continues chaining promises until resolve(b)
执行继续链接承诺直到
resolve(b)
b
is a Promise that is passed as resolve value for Promise A. This generates a new microtask that chains B to A. b
是一个 Promise,作为 Promise A 的解析值传递。这会生成一个新的微任务,将 B 链接到 A。
End of main block, two microtasks in the queue: chain-D-to-C
, chain-B-to-A
.主块结束,队列中有两个微任务:
chain-D-to-C
, chain-B-to-A
。
execution of chain-D-to-C
: chain-D-to-C
执行:
d.then(c.resolve, c.reject)
d.then(c.resolve, c.reject)
then1
is enqueued then1
入队execution of chain-B-to-A
: chain-B-to-A
执行:
b.then(a.resolve, a.reject)
b.then(a.resolve, a.reject)
microtask queue a this moment: then1
microtask queue a 这一刻:
then1
execution of then1
: then1
的执行:
b
, this enqueues the then-BA
microtaskb
,这会将then-BA
微任务排入队列then
resolves and enqueues a microtask for catch1
then
生成的 Promise 为catch1
解析并入队一个微任务microtask queue a this moment: then-BA
, catch1
microtask queue a 这一刻:
then-BA
, catch1
execution of then-BA
: then-BA
的执行:
externalThen
externalThen
解析并入队一个微任务execution of catch1
: catch1
的执行:
finally1
finally1
一个微任务microtask queue a this moment: externalThen
, finally1
microtask queue a 这一刻:
externalThen
, finally1
execution of externalThen
: prints "DONE" externalThen
的执行:打印“DONE”
execution of finally1
: prints "FINALLY" finally1
的执行:打印“FINALLY”
no more microtaks, code terminates没有更多的 microtaks,代码终止
// Promise A
new Promise(resolve => {
// Promise B
const b = new Promise<void>(resolve => {
// Promise C
new Promise(resolve => {
// Promise D
resolve(Promise.resolve("A"));
})
.then(function then1() {
console.log("THEN");
resolve();
})
.finally(function finally1() {
console.log("FINALLY");
});
});
resolve(b);
})
.then(function externalThen() {
console.log("DONE");
});
All identical to case 2 until here:直到这里都与案例 2 相同:
then1
then1
then1
: then1
的执行:
b
, this enqueues the then-BA
microtaskb
,这会将then-BA
微任务排入队列then
resolves and enqueues a microtask for finally1
then
生成的 Promise 为finally1
解析并入队一个微任务then-BA
, finally1
then-BA
, finally1
then-BA
: then-BA
的执行:
externalThen
externalThen
解析并入队一个微任务finally1
: prints "FINALLY" finally1
的执行:打印“FINALLY”externalThen
externalThen
externalThen
: prints "DONE" externalThen
的执行:打印“DONE”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.