Отже, ви в основному запитуєте, в чому різниця між цими двома (де 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).