鉴于这个 Promise 链。
function getData() {
return new Promise((resolve) => {
// ...
})
.then((data) => data.someData)
.then((rawData) => processData(rawData))
.catch((err) => console.log(err));
}
我有两个问题:
then() 安排一个回调在其附加的 Promise 实例看到其状态从“待处理”更改为“已完成”时运行(以及安排在状态从“待处理”更改为“时运行的另一个可选回调”)拒绝”)。但是,这种调度是如何运作的却相当模糊。我的意思是,由于 then() 方法(而不是传递给它的回调)本身同步运行,那么这个“调度”是如何执行的? Promise 实例是否有某种与已完成和已拒绝状态相关联的内部列表,然后()将回调推送到这些列表中,然后,当状态发生更改时,将回调推送到微任务队列中?同样的问题也适用于 catch()。
既然我们正在讨论catch(),假设我们在上面代码片段的then()链中的某个地方有一个错误。由于我们只将第一个回调函数(处理成功)传递给 then() 链,因此错误会以某种方式沿着链传播到 catch() 块并在那里进行处理。但同样,目前还不清楚这是否有效。我的意思是,then() 返回一个新的 Promise 实例,在我看来,这些 Promise 实例是独立的,因为它们有自己单独的状态和自己单独的计划回调列表(如果这个假设成立),并捕获() 通常只会向由
then((rawData) => processData(rawData))
创建的最后一个 Promise 实例注册“拒绝”状态的回调。
Promise 实例是否有某种与已完成和拒绝状态相关联的内部列表,然后()将回调推送到这些列表中,然后,当状态发生变化时,回调被推送到微任务队列中?
是的,正是如此。
同样的问题也适用于 catch()。
同样的事情。事实上,为了方便起见,
catch
只是对 then
的包装,字面上实现为
// class Promise {
…
catch(onRejected) {
return this.then(undefined, onRejected);
}
错误以某种方式沿着链传播到 catch() 块并在那里进行处理。但是这些 Promise 实例是独立的,因为它们有自己单独的状态和自己单独的计划回调列表,因此 catch() 通常只会为最后一个 Promise 实例注册“拒绝”状态的回调?
是的,会的。解决方案是,错误传播并不是通过神奇地确定并跳转到最近的错误处理程序来实现的,而是在链中一个接一个地拒绝另一个承诺。
由
.then(onFulfilled, onRejected)
创建的 Promise 将通过相应处理程序回调的结果进行解析(当执行该回调时),或者在该回调抛出时被拒绝。如果您不为参数传递任何回调,如.then(onFulfilled, undefined)
、.then(undefined, onRejected)
甚至.then(undefined, undefined)
,则then
方法仍然会在其接收器上注册两个状态更改的反应,并且默认情况下将结果或错误转发到其结果承诺中。
因此,当该链中的第一个 Promise 拒绝时,其上会有一个拒绝反应,该反应将拒绝第二个 Promise,这将依次安排其拒绝反应,这将拒绝第三个 Promise,这将依次安排处理程序
.catch()
已在其上注册。