Могу ли я сломать цепочку раньше с помощью bluebird Promises?
Я не обязательно хочу ошибки, но у меня есть:
getFromDb().then (tradeData) ->
if not tradeData
# DO NOT CONTINUE THE CHAIN
else
getLatestPrice tradeData
.then (latestPrice) ->
...
.then ->
...
.then ->
...
.catch (err) ->
next err
Любой способ для меня прервать цепочку, если нет tradeData?
Ответы
Ответ 1
getFromDb().then (tradeData) ->
if tradeData
getLatestPrice tradeData ->
.then (latestPrice) ->
...
.then ->
...
.then ->
...
.catch (err) ->
next err
else
getSomethingElse ->
send("no data")
В версии 3.0 вы сможете это сделать:
p = getFromDb().then (tradeData) ->
if not tradeData
send("no data");
p.break()
else
getLatestPrice tradeData
.then (latestPrice) ->
...
.then ->
...
.then ->
...
.catch (err) ->
next err
Ответ 2
Несмотря на принятый ответ, но я хотел бы сказать всем искателям, что функция "break()" была изменена на "cancel()"
Используйте что-то вроде этого:
p = getFromDb().then (tradeData) ->
if not tradeData
send("no data");
p.cancel(); // Look Here!!!!!!!!!!!!!!!!
else
getLatestPrice tradeData
.then (latestPrice) ->
...
.then ->
...
.then ->
...
.catch (err) ->
next err
До этого обязательно добавьте следующие строки в config:
Promise.config({
cancellation: true
});
Ответ 3
Мне просто интересно, почему бы не воспользоваться тем фактом, что вы можете throw
все, что захотите, а не только что-то, что есть instanceof Error
. Это считается плохой практикой? По-моему, это зависит от того, чего вы пытаетесь достичь. Цепочка обещаний может быть прервана по разным причинам, но в целом эти два будут разделены на две группы. Classic error occur
и early break in chain
. Логически второй нельзя считать чем-то, что должно быть instance of Error
.
const handleError = (err) => {
...
}
const skip = (reason, ..., ...) => {
/**
* construct whatever you like
* just for example here return reason
*/
return reason
}
Promise.resolve()
.then(() => {
if (iShouldEndChainEarlier) {
throw skip('I would like to end chain earlier')
}
return asyncOperation1()
})
.then(results => {
...
return asyncOperation2(results)
})
.then(... => {
...
})
.catch(interrupt => {
if (interrupt instanceof Error) {
return handleError(interrupt)
}
/**
* Handle breaking promise chain earlier
* having interrupt reason in scope
*/
})
Если логически, ранний разрыв в цепочке можно рассматривать как ошибку (что может быть полностью выполнено), вы можете создать свою собственную ошибку и провести различие между двумя в блоке catch
. Поэтому просто говорим, что можно подумать о другом подходе (-ях) при обработке любого прерывания, которое может произойти в цепочке обещаний.
Мы могли бы утверждать, что это можно считать чем-то против first error pattern
в node. Если существует ошибка, лучшим способом было бы вызвать обратный вызов, например callback(err)
, где err
действительно должен быть instanceof Error
иначе callback(null, data)
. Но с другой стороны, имея в виду, что .catch(fn)
для меня просто для сахара then(undefined, onRejected)
, он кажется достаточно хорошим для обработки параметра onRejected
, основанного на ситуации, в которой вы находитесь.