并发承诺的顺序如何在异步函数中工作?
How does the order of concurrent promises work in an asynchronous function?
我注意到 MDN:
中的并发承诺示例
async function foo() {
const p1 = new Promise((resolve) => setTimeout(() => resolve('1'), 1000))
const p2 = new Promise((_,reject) => setTimeout(() => reject('2'), 500))
const results = [await p1, await p2];
}
foo().catch(() => {}) // Attempt to swallow all errors...
MDN 声明:
in the following code an unhandled promise rejection error will be thrown, even if a .catch handler has been configured further along the promise chain. This is because p2 will not be "wired into" the promise chain until control returns from p1.
这到底是什么意思?如果await
先等待p1
的promise解决,那么为什么p2
会出现拒绝错误呢?我是异步函数的新手,非常感谢任何新见解!
问题是解释器在等待 p1 时并没有等待 p2 的 promise 解决。在它越过线 await p2
之前,p2
基本上是悬空的 - 它没有连接到任何其他东西 直到 它被 await
ed。因此,如果 p2 在连接到 .catch
之前抛出 - 通过函数本身的 .catch
,或通过 await
,将其连接到外部 .catch
- 你会收到未处理的拒绝。
说明相同问题的另一种方式,仅使用一个 Promise:
function foo() {
const p2 = new Promise((_,reject) => setTimeout(() => reject('2'), 500))
setTimeout(() => {
p2.catch(() => {});
}, 1000);
}
foo();
在您的代码段示例中,p1 的重要性仅在于它会在遇到 await p2
表达式之前造成延迟。在我上面的示例中,setTimeout
正在做类似的事情 - 它附加了一个 .catch
处理程序 在 承诺被拒绝后,导致未处理的拒绝。
在您的程序中添加一些 console.log
语句将有助于您查看操作顺序
async function foo() {
console.log("foo")
const p1 = new Promise((resolve) => {
console.log("p1 promise")
setTimeout(_ => {
console.log("p1 resolve")
resolve('1')
}, 1000)
})
const p2 = new Promise((_,reject) => {
console.log("p2 promise")
setTimeout(_ => {
console.log("p2 reject")
reject('2')
}, 500)
})
console.log("results")
return [
(console.log("await p1"), await p1),
(console.log("await p2"), await p2)
]
}
foo().then(console.log, console.error)
输出
order
console.log
1
foo
2
p1 promise
3
p2 promise
4
results
5
await p1
6
p2 reject
7
p1 resolve
8
await p2
9
Error: 2
说明
所以当我们运行foo
时,预计我们会看到消息1,"foo" ,首先,因为那是程序的第一行。
下一个 p1
被创建,我们看到消息 2,“p1 promise”。这表明 new Promise(... => body)
的 body
立即是 运行。
下一个 p2
被创建,我们看到消息 3,"p2 promise",如下同上解释。
接下来我们看到消息4,“结果”。如果您希望看到 setTimeout
内的消息,这些消息在事件队列中会延迟,我们稍后会看到它们。这是 setTimeout
的明确目的
接下来是消息5,“await p1”,我们正在等待p1
解决。
当我们等待 p1
解决时,p2
拒绝并且我们看到消息 6, “p2 拒绝”.
p1
终于解决了,我们看到消息 7, "p1 resolve".
接下来我们移动到结果数组中的最终值,我们发出消息 8,"await p2". p2
此时已经完成,导致拒绝错误。此时 foo
立即退出,对 foo()
的调用导致拒绝承诺。如果这个点之后还有代码,就不会是运行了。这与 throw
ing 同步代码中的错误相同。
最后我们看到消息9, "Error: 2",这是[=27的结果=] 捕获 foo()
返回的被拒绝的承诺
我注意到 MDN:
中的并发承诺示例async function foo() {
const p1 = new Promise((resolve) => setTimeout(() => resolve('1'), 1000))
const p2 = new Promise((_,reject) => setTimeout(() => reject('2'), 500))
const results = [await p1, await p2];
}
foo().catch(() => {}) // Attempt to swallow all errors...
MDN 声明:
in the following code an unhandled promise rejection error will be thrown, even if a .catch handler has been configured further along the promise chain. This is because p2 will not be "wired into" the promise chain until control returns from p1.
这到底是什么意思?如果await
先等待p1
的promise解决,那么为什么p2
会出现拒绝错误呢?我是异步函数的新手,非常感谢任何新见解!
问题是解释器在等待 p1 时并没有等待 p2 的 promise 解决。在它越过线 await p2
之前,p2
基本上是悬空的 - 它没有连接到任何其他东西 直到 它被 await
ed。因此,如果 p2 在连接到 .catch
之前抛出 - 通过函数本身的 .catch
,或通过 await
,将其连接到外部 .catch
- 你会收到未处理的拒绝。
说明相同问题的另一种方式,仅使用一个 Promise:
function foo() {
const p2 = new Promise((_,reject) => setTimeout(() => reject('2'), 500))
setTimeout(() => {
p2.catch(() => {});
}, 1000);
}
foo();
在您的代码段示例中,p1 的重要性仅在于它会在遇到 await p2
表达式之前造成延迟。在我上面的示例中,setTimeout
正在做类似的事情 - 它附加了一个 .catch
处理程序 在 承诺被拒绝后,导致未处理的拒绝。
在您的程序中添加一些 console.log
语句将有助于您查看操作顺序
async function foo() {
console.log("foo")
const p1 = new Promise((resolve) => {
console.log("p1 promise")
setTimeout(_ => {
console.log("p1 resolve")
resolve('1')
}, 1000)
})
const p2 = new Promise((_,reject) => {
console.log("p2 promise")
setTimeout(_ => {
console.log("p2 reject")
reject('2')
}, 500)
})
console.log("results")
return [
(console.log("await p1"), await p1),
(console.log("await p2"), await p2)
]
}
foo().then(console.log, console.error)
输出
order | console.log |
---|---|
1 | foo |
2 | p1 promise |
3 | p2 promise |
4 | results |
5 | await p1 |
6 | p2 reject |
7 | p1 resolve |
8 | await p2 |
9 | Error: 2 |
说明
所以当我们运行
foo
时,预计我们会看到消息1,"foo" ,首先,因为那是程序的第一行。下一个
p1
被创建,我们看到消息 2,“p1 promise”。这表明new Promise(... => body)
的body
立即是 运行。下一个
p2
被创建,我们看到消息 3,"p2 promise",如下同上解释。接下来我们看到消息4,“结果”。如果您希望看到
的明确目的setTimeout
内的消息,这些消息在事件队列中会延迟,我们稍后会看到它们。这是setTimeout
接下来是消息5,“await p1”,我们正在等待
p1
解决。当我们等待
p1
解决时,p2
拒绝并且我们看到消息 6, “p2 拒绝”.p1
终于解决了,我们看到消息 7, "p1 resolve".接下来我们移动到结果数组中的最终值,我们发出消息 8,"await p2".
p2
此时已经完成,导致拒绝错误。此时foo
立即退出,对foo()
的调用导致拒绝承诺。如果这个点之后还有代码,就不会是运行了。这与throw
ing 同步代码中的错误相同。最后我们看到消息9, "Error: 2",这是[=27的结果=] 捕获
返回的被拒绝的承诺foo()