Автор оригинала: FreeCodeCamp Community Member.
Макс Бельский
Самые популярные статьи описывают разницу между Chav и 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 никогда не обрабатывает отвергнутые обещания из того же . Затем (наверняка)
Обратный вызов и .catch
занимает оба. Однако помимо разницы поведения есть еще один нюанс. Это о том, как эти способы будут переведены на Микрозащитныеки И как они будут очередными. Давайте посмотрим на пример разницы.
Обещание
Есть задача – напиши Обещание.race
полифилл. Мы используем общий рисунок в обеих функциях для обработки разрешено
Обещания и разные инструменты для обработки отклонено
обещания.
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)) }) })}
Попробуйте некоторые тесты, чтобы убедиться, что оба решения работают хорошо:
// 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()
Как видите, оба полифиллирования работают как ожидалось. Аргументы Заказ и отклонено
Обещает обработчик обработки не имеет значения. Пока мы не попробуем его с следующим набором тестов:
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) // ???
Пятый, шестой и седьмой гонки возвращают ожидаемые ценности. Как насчет восьмого? Вместо Отклонить
Это возвращает Решить
И это не ошибка.
Queue MicroTasks
В зависимости от результата работы, ожидающий обещание меняет свое состояние в разрешено
или отклонено
Отказ Окружающая среда JS ставит это обещание в очереди MicroTasks. Как описано в ECMA 2015 Спецификация Эта очередь работает по FIFO Принцип – во-первых, во-первых. База на этом, давайте рассмотрим дело восьмой гонки.
В начале гонки у нас уже есть две очередные обещания, и первое отклонение. .then
Без второго аргумента не может справиться с отклоненным обещанием, поэтому оно ставит обещание обратно в очередь. И вместо того, чтобы обращаться с этим обещанием с .catch
Окружающая среда JS переключается на P2
Потому что он имеет более высокие приоритеты в очереди.
На следующий тик .then
Ручки P2
И гонка заканчивается Решить
результат.
В следующий раз, когда вы выбираете в обработчиках по уловам и OneRected, помните не только, которые отвергли обещания, которые они поймают, но и о разнице в очереди!