home

Cancelling Long Promise Chains

Jul 02, 2014

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.