Promise 的 .then 和 .catch 是如何工作的?

Posted

技术标签:

【中文标题】Promise 的 .then 和 .catch 是如何工作的?【英文标题】:How does Promise's .then and .catch work under the hood? 【发布时间】:2021-07-28 20:51:50 【问题描述】:

我已经知道 Promise 是如何工作的,但我正在尝试更深入地研究以加强我的基础!

所以在阅读了这么多 *** 帖子后,我发现,每个 promise 对象中都有两个主要的数组属性,称为 onFulfillment 和 onRejection,它们是空数组,我们使用 .then 填充 onFulfillment 数组和 .catch 或 .then 的第二个参数填充 onRejection 空数组!

一旦我们的承诺得到落实,这些数组中的函数就会被放入微任务队列中以供稍后执行。

如果我们的 promise 被解决,隐藏的 onFulfillment 数组中的函数将被放入任务队列,但如果我们的 promise 被拒绝,onRejection 数组中的函数将被放入任务队列以供稍后执行,但是,当我测试这个理论时,好像不是这样的!

我确定我的英语不容易理解,所以这里有一些代码,希望能让大家对我在说什么有所了解。

let p = new Promise(function (resolve, reject)

  setTimeout(reject, 1000)

)

p.then(x => console.log('done'))
.then(null, x => console.log(true))

p.catch(x => console.log('done'))

我们有一个 .then 和一个 .catch ,我们分别放入 onFulfillment 和 onRejection 数组,1000 毫秒后,放入微任务队列的函数取决于我们的承诺是解决还是拒绝。在我们的例子中,它被拒绝了,所以将 .catch 的函数放到微任务队列中才有意义,然而,似乎 .then 的函数也被放到了任务队列中!

它并没有真正运行,但它被评估为被拒绝的承诺,但如果是这样的话,.then 的函数被放入微任务队列并运行/评估,这意味着它不正确的是,运行什么函数取决于我们的承诺已解决或被拒绝,似乎 .then 和 .catch 都将运行/评估。

【问题讨论】:

here's a bunch of promise implementations - 阅读代码,看看幕后发生了什么 - 我发现“PinkySwear.js”最容易理解 - 整个解决过程也在该网站上进行了深入描述 - @987654322 @ 所有 then() 和 catch() 回调最初都会被捕获,但哪些回调最终会被推送到任务队列中执行,这取决于 Promise 最终是解析还是拒绝。 “所以只有将 .catch 的函数放到微任务队列中才有意义” - 为什么? .then() 最多接受两个函数。第一个将在满足Promise 的情况下执行,第二个将在任何其他情况下执行。第二个.then() 的结果是被拒绝的Promise,它不是.catch()ed,因此触发了最后的“catch all”。 【参考方案1】:

我们使用.then 填充onFulfillment 数组,使用.catch.then 的第二个参数填充onRejection 空数组!

不完全是。 then 总是将处理程序放在两个数组中,以便在承诺解决时得到通知。这些处理程序(不是传递的参数!)然后

要么使用结果/错误值调用相应的回调,然后解决 .then() 已返回的带有调用结果的承诺, 或者,如果没有传递相应状态的回调,则直接将值传播到 .then() 返回的承诺

您可以使用 .then(onFulfilled, onRejected).then(onFulfilled, null).then(null, onRejected).then(null, null) - 它们都安装了两个处理程序。

【讨论】:

以上是关于Promise 的 .then 和 .catch 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

es6 promise的catch 和 then 的区别认识

Promise 的 .then 和 .catch 是如何工作的?

关于promise中reject和catch的问题

如果使用 then ,是不是需要在 promise 中嵌套 catch?

Promise的.then .catch

在 Promise 中,使用 catch 和 then 的第二个参数有啥区别? [复制]