catch与onRejected之间的真正区别

by Max Belsky

通过Max Belsky

catch与onRejected之间的真正区别 (The real difference between catch vs onRejected)

Most popular articles describe the difference between catch and onRejected in a code snippet like this:

最受欢迎的文章在​​这样的代码片段中描述了catch和onRejected之间的区别:

const getPromise = () => new Promise((resolve, reject) => {  Math.round(Math.random()) ?     resolve('resolve #1') :     reject('reject #1')})
getPromise().then(result => {  throw new Error('reject #2')}, error => {  // Handles only 'reject #1'})
getPromise().then(result => {  throw new Error('reject #2')})  .catch(error => {    // Handles both 'reject #1',     // and 'reject #2'  }))

onRejected never handles rejected promises from the same .then(onFulfilled) callback and .catch takes both. However besides the behavior difference, there is one more nuance. It’s about how these ways will be translated to microtasks and how they will be queued.Let’s see an example of the difference.

onRejected永远不会处理来自同一.then(onFulfilled)回调和.catch两者的拒绝承诺。 但是,除了行为差异外,还有其他细微差别。 这是关于如何将这些方式转换为微任务以及如何将它们排队的方法。让我们来看一个区别的例子。

无极种族 (Promise.race)

There is a task — write Promise.race polyfill. We use a common pattern in both functions to handle resolved promises and different tools to handle rejected promises.

有一个任务-编写Promise.race 。 我们在两个函数中使用通用模式来处理已resolved承诺,并使用不同的工具来处理已rejected承诺。

const promiseRaceOnRejected = (promises = []) => {  return new Promise((resolve, reject) => {    promises.forEach(promise => {      promise.then(        result => resolve(result),        error => reject(error)      )    })  })}
const promiseRaceCatch = (promises = []) => {  return new Promise((resolve, reject) => {    promises.forEach(promise => {      promise.then(result => resolve(result))        .catch(error => reject(error))    })  })}

Try some tests to be sure that both solutions work well:

请尝试一些测试,以确保两种解决方案都能正常工作:

// A helper function to create a delayed promiseconst getPromise = (resolveMs, rejectMs) => {  return new Promise((resolve, reject) => {    if ('number' === typeof rejectMs) {      setTimeout(() => reject(rejectMs), rejectMs)    }
if ('number' === typeof resolveMs) {      setTimeout(() => resolve(resolveMs), resolveMs)    }  })}
const testRaces = async () => {  const r1 = await promiseRaceOnRejected([    getPromise(0),     getPromise(5)  ])  // 0
const r2 = await promiseRaceCatch([    getPromise(0),     getPromise(5)  ])  // 0
const r3 = await promiseRaceOnRejected([    getPromise(5),     getPromise(null, 2)  ])    .catch(e => e)  // 2
const r4 = await promiseRaceCatch([    getPromise(5),     getPromise(null, 2)  ])    .catch(e => e)  // 2}
testRaces()

As you can see, both polyfills work as expected. Arguments order and rejected promises handler variation don’t matter. Until we try it with the next set of tests:

如您所见,这两个polyfills都可以正常工作。 参数顺序和rejected诺言处理程序的变化无关紧要。 直到我们尝试下一组测试:

const r5 = await promiseRaceOnRejected([    Promise.resolve('Resolve'),     Promise.reject('Reject')  ])  // Resolve
const r6 = await promiseRaceCatch([    Promise.resolve('Resolve'),     Promise.reject('Reject')  ])  // Resolve
const r7 = await promiseRaceOnRejected([    Promise.reject('Reject'),     Promise.resolve('Resolve')  ])    .catch(e => e)  // Reject
const r8 = await promiseRaceCatch([    Promise.reject('Reject'),     Promise.resolve('Resolve')  ])    .catch(e => e)  // ???

The fifth, sixth and seventh races return expected values. What about the eighth? Instead of Reject it returns Resolve and it is not a bug.

第五,第六和第七场比赛返回期望值。 那第八呢? 它返回Resolve而不是Reject ,这不是bug。

微任务队列 (Microtasks queue)

Depending on the job’s result, a pending promise changes its state to resolved or rejected. JS environment puts that promise in a microtasks queue. Like it described in ECMA 2015 specification, this queue works by the FIFO principle — first in, first out. Base on this, let’s review the eighth race’s case.

根据作业的结果,未完成的承诺会将其状态更改为已resolved或已rejected 。 JS环境将该承诺放在微任务队列中。 就像ECMA 2015 规范中描述的那样,此队列按照FIFO原则工作- 先进先出 。 基于此,让我们回顾一下第八场比赛的情况。

At the start of the race, we already have two queued promises, and the rejected is first. .then without a second argument cannot handle a rejected promise, so it puts the promise back into the queue. And instead of handling this promise with .catch, the JS environment switches to p2 because it has higher priorities in the queue.

在比赛开始时,我们已经有两个排队的诺言,被拒绝的是第一个。 .then如果没有第二个参数,则无法处理被拒绝的诺言,因此会将诺言重新放入队列。 而不是使用.catch处理此承诺,JS环境切换到p2因为它在队列中具有更高的优先级。

On next tick .then handles p2 and the race ends with Resolve result.

在下一个刻度上.then处理p2 ,比赛以Resolve结果结束。

Next time when you’re choosing between the catch and onRejected handlers, remember not only which rejected promises they catch, but about the queuing difference too!

下次当您在catch和onRejected处理程序之间进行选择时,不仅要记住它们捕获了哪些拒绝的承诺,还要记住排队的区别!

翻译自: https://www.freecodecamp.org/news/the-real-difference-between-catch-vs-onrejected-15cab8978e92/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值