Отже, ви в основному запитуєте, в чому різниця між цими двома (де p
обіцянка, створена з попереднього коду):
return p.then(...).catch(...);
і
return p.catch(...).then(...);
Існують відмінності або тоді, коли p вирішує чи відхиляє, але чи важливі ці відмінності чи ні, залежить від того, що робить код всередині .then()
або .catch()
обробники.
Що відбувається при p
вирішенні:
У першій схемі при p
вирішенні .then()
викликається обробник. Якщо цей .then()
обробник поверне значення або інша обіцянка, яка врешті-решт вирішиться, .catch()
обробник пропускається. Але, якщо .then()
обробник або кидає, або повертає обіцянку, яка врешті-решт відхиляє, .catch()
обробник виконує як відхилення в початковій обіцянці p
, так і помилку, яка виникає в .then()
обробнику.
У другій схемі при p
вирішенні .then()
викликається обробник. Якщо цей .then()
обробник або кидає, або повертає обіцянку, яка врешті-решт відхиляє, .catch()
обробник не може це зрозуміти, тому що це перед цим у ланцюжку.
Отже, це різниця №1. Якщо .catch()
обробник знаходиться ПІСЛЯ, то він також може виявити помилки всередині .then()
обробника.
Що відбувається при p
відхиленні:
Тепер у першій схемі, якщо обіцянка p
відхилиться, .then()
обробник пропущений і .catch()
обробник буде викликаний так, як ви очікували. Те, що ви робите в .catch()
обробнику, визначає, що повертається як кінцевий результат. Якщо ви просто повертаєте значення від .catch()
обробника або повертаєте обіцянку, яка врешті-решт вирішиться, ланцюг обіцянок переходить у вирішений стан, оскільки ви "обробили" помилку і повернулися нормально. Якщо ви кинете або повернете відхилену обіцянку в .catch()
обробнику, то повернута обіцянка залишається відхиленою.
У другій схемі, якщо обіцянку p
відхиляє, тоді .catch()
викликається обробник. Якщо ви повернете нормальне значення або обіцянку, яка врешті-решт вирішиться з .catch()
обробника (таким чином "обробляючи" помилку), ланцюг обіцянок переходить у вирішений стан, і .then()
обробник після заклику .catch()
буде викликаний.
Отже, це різниця №2. Якщо .catch()
обробник є ДО ПЕРЕД, то він може виправити помилку і дозволити .then()
оброблювачеві все ще викликати.
Коли користуватися якими:
Скористайтеся першою схемою, якщо ви хочете лише один .catch()
обробник, який може виявити помилки або в оригінальній обіцянці, p
або в .then()
обробнику, і відхилення від p
повинно пропустити .then()
обробник.
Використовуйте другу схему, якщо ви хочете отримати можливість помилок у початковій обіцянці p
і, можливо, (залежно від умов) дозвольте ланцюжку обіцянок продовжуватись як вирішено, виконуючи таким чином .then()
обробник.
Інший варіант
Є ще один варіант використання обох зворотних викликів, на які можна перейти, .then()
як у:
p.then(fn1, fn2)
Це гарантує, що тільки один fn1
або fn2
коли-небудь буде викликаний. Якщо p
вирішує, то fn1
буде викликано. Якщо p
відхиляє, тоді fn2
буде викликано. Ніяка зміна результату fn1
ніколи не fn2
може викликати дзвінки або навпаки. Отже, якщо ви хочете зробити абсолютно впевненим, що викликається лише один з двох ваших обробників, незалежно від того, що відбувається в самих обробниках, тоді ви можете використовувати p.then(fn1, fn2)
.