Ответ 1
Итак, в основном вы спрашиваете, в чем разница между этими двумя (где 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()
равен AFTER, он также может ловить ошибки внутри обработчика .then()
.
Что происходит, когда p
отклоняет:
Теперь, в первой схеме, если обещание p
отклоняется, тогда обработчик .then()
пропускается, и обработчик .catch()
будет вызван так, как вы ожидали. То, что вы делаете в обработчике .catch()
, определяет то, что возвращается в качестве конечного результата. Если вы просто возвращаете значение из обработчика .catch()
или возвращаете обещание, которое в конечном итоге разрешается, то цепочка обещаний переключается в разрешенное состояние, потому что вы "обрабатывали" ошибку и возвращались нормально. Если вы отбросили или вернули отклоненное обещание в обработчике .catch()
, тогда возвращаемое обещание останется отклоненным.
Во второй схеме, если обещание p
отклоняется, вызывается обработчик .catch()
. Если вы возвращаете нормальное значение или обещание, которое в конечном итоге разрешается с помощью обработчика .catch()
(таким образом, "обрабатывая" ошибку), то цепочка обещаний переключается в разрешенное состояние, а обработчик .then()
после вызова .catch()
.
Так что разница # 2. Если обработчик .catch()
BEFORE, он может обрабатывать ошибку и разрешать обработчик .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)
.