Cancelling Long Promise Chains
My previous introduction to promises left out a common case: cancelling a chain of promise. Ideally, this is something you won't have to do too often; but for the one or two times when you run into it, here's one solution to handle it.
First though, the problem. Pretend you have a chain of promises, this could be a controller that has to go through multiple steps and transformation:
Promise = require('bluebird')
a = -> Promise.resolve('1')
b = -> Promise.resolve('2')
c = -> Promise.resolve('3')
a().then (value) ->
console.log(value)
b()
.then (value) ->
console.log(value)
c()
.then (value) ->
console.log(value)
The above prints 1
, 2
and 3
. However, we'd like to change our code to stop processing when a()
returns null
. As a practical example, think of a controller loading a record by id and quickly returning a 404 if that id isn't found.
The solution is to cancel our promise. With Bluebird, the promise library I'm using here, this first requires that we mark our promise as cancellable
. Next we can cancel the promsie and finally handle the cancellation:
p = a().then (value) ->
console.log(value)
return p.cancel() if value == null
b()
.then (value) ->
console.log(value)
c()
.then (value) ->
console.log(value)
.catch Promise.CancellationError, ->
console.log('cancelled')
.cancellable()
With the above code, when a()
returns null
, our output will be null
followed by cancelled
. It's possible to cancel
with an explicit reason, or we can cancel
without a reason and catch the Promise.CancellationError
type.