Когда есть. То (успех, неудача) считается антипаттерном для promises?
112 user2127480 [2014-07-09 22:31:00]
Я рассмотрел рекомендацию по обещанию bluebird, в которой упоминается, что .then(success, fail) является антипаттерном. Я не совсем понимаю его объяснение, как попытку и улов.
Что не так с этим?
some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
Кажется, что пример предлагает правильное использование следующего.
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
Какая разница?
javascript node.js promise bluebird
4 ответа
132 Bergi [2014-07-09 23:35:00]
Какая разница?
Вызов .then() возвращает обещание, которое будет отклонено, если обратный вызов вызывает ошибку. Это означает, что если ваш успех logger не удался, ошибка будет передана в следующий обратный вызов .catch(), но не к обратному сообщению fail, который идет вместе с success.
Здесь диаграмма управляющего потока:


Чтобы выразить это в синхронном коде:
// some_promise_call().then(logger.log, logger.log)
then: {
try {
var results = some_call();
} catch(e) {
logger.log(e);
break then;
} // else
logger.log(results);
}
Второй log (который похож на первый аргумент .then()) будет выполняться только в том случае, если исключение не было. Обозначенный блок и оператор break кажутся немного странными, на самом деле это python имеет try-except-else для (рекомендуемое чтение!).
// some_promise_call().then(logger.log).catch(logger.log)
try {
var results = some_call();
logger.log(results);
} catch(e) {
logger.log(e);
}
Логгер catch также будет обрабатывать исключения из вызова журнала ошибок.
Так много для разницы.
Я не совсем понимаю его объяснение, как для try and catch
Аргумент состоит в том, что обычно вы хотите поймать ошибки на каждом шаге обработки и не использовать их в цепочках. Ожидается, что у вас будет только один конечный обработчик, который обрабатывает все ошибки. В то время как при использовании "antipattern" ошибки в некоторых из обратных вызовов не обрабатываются.
Однако этот шаблон действительно очень полезен: когда вы хотите обрабатывать ошибки, которые произошли именно на этом шаге, и вы хотите сделать что-то совершенно другое, если ошибка не произошла - то есть когда ошибка невосстановима. Помните, что это ветвление вашего потока управления. Конечно, это иногда желательно.
Что не так с этим?
some_promise_call() .then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
Чтобы повторить обратный вызов. Вы скорее хотите
some_promise_call()
.catch(function(e) {
return e; // it OK, we'll just log it
})
.done(function(res) {
logger.log(res);
});
Вы также можете использовать .finally() для этого.
28 acjay [2014-07-09 23:30:00]
Оба не совсем идентичны. Разница в том, что в первом примере не будет обнаружено исключение, которое было бы выбрано в вашем обработчике success. Поэтому, если ваш метод должен только возвращать разрешенный promises, как это часто бывает, вам нужен трейлингер catch (или еще один then с пустым success параметром). Конечно, может быть, ваш обработчик then не сделает ничего, что потенциально может потерпеть неудачу, и в этом случае использование одного 2-параметра then может быть прекрасным.
Но я считаю, что точка текста, с которой вы связаны, заключается в том, что then в основном полезен против обратных вызовов в его способности связывать множество асинхронных шагов, а когда вы на самом деле делаете это, 2-параметрическая форма then тонко не ведет себя так, как ожидалось, по вышеуказанной причине. Это особенно противоречиво при использовании средней цепи.
Как кто-то, кто сделал много сложного асинхронного материала и натолкнулся на такие углы больше, чем я хотел бы признать, я действительно рекомендую избегать этого анти-шаблона и идти с помощью отдельного подхода к обработчикам.
12 aWebDeveloper [2016-03-20 17:55:00]
Изучая преимущества и недостатки обоих, мы можем сделать расчетное предположение о том, что подходит для ситуации. Это два основных подхода к реализации promises. У обоих есть плюсы и минус
Catch Approach
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
<сильные > Преимущества
- Все ошибки обрабатываются одним блоком catch.
- Даже улавливает любое исключение в блоке then.
- Цепочка множественных обратных вызовов успеха
Недостатки
- В случае цепочки становится трудно отображать разные сообщения об ошибках.
Подход к успеху/ошибкам
some_promise_call()
.then(function success(res) { logger.log(res) },
function error(err) { logger.log(err) })
<сильные > Преимущества
- Вы получаете мелкозернистый контроль ошибок.
- У вас может быть обычная функция обработки ошибок для различных категорий ошибок, таких как ошибка db, ошибка 500 и т.д.
Disavantages
- Вам все равно потребуется еще один
catch, если вы хотите обработать ошибки, вызванные обратным вызовом успеха
1 ktretyak [2017-12-28 19:37:00]
Вместо слов, хороший пример. Следующий код (если первое обещание разрешено):
Promise.resolve()
.then
(
() => { throw new Error('Error occurs'); },
err => console.log('This error is caught:', err)
);
идентичен:
Promise.resolve()
.catch
(
err => console.log('This error is caught:', err)
)
.then
(
() => { throw new Error('Error occurs'); }
)
Но, отвергнув первое обещание, это не идентично:
Promise.reject()
.then
(
() => { throw new Error('Error occurs'); },
err => console.log('This error is caught:', err)
);
Promise.reject()
.catch
(
err => console.log('This error is caught:', err)
)
.then
(
() => { throw new Error('Error occurs'); }
)