Bluebird Promise Cancellation

2019-05-11 16:51发布

问题:

Say I have the following Promise chain:

var parentPromise = Promise.resolve()
  .then(function () {
    var condition = false;
    if (condition) {
      return parentPromise.cancel('valid reason');
    } else {
      return Promise.resolve()
        .then(function () {
          var someOtherCondition = true;
          if (someOtherCondition) {
            console.log('inner cancellation');
            return parentPromise.cancel('invalid reason');
          }
        });
    }
  })
  .catch(Promise.CancellationError, function (err) {
    console.log('throwing');
    if (err.message !== 'valid reason') {
      throw err;
    }
  })
  .cancellable();

The above never enters the catch.

If we swap condition to true, the inner cancellation is never hit, but the catch is still not triggered.

removing the .cancellable at the end , and replacing all instances of parentPromise.cancel() with explicit throw new Promise.CancellationError() "fixes" the problem. What I don't understand is why?

Why was the original approach not working?

I am using bluebird 2.3.11.

回答1:

cancellable() creates cancellable promises and only they throw CancellationError by default, when cancel function is called with out any reason.

In your case, you are making the promise cancellable only after attaching the catch handler. But the promise is not cancellable yet. So, cancel function call will not raise Promise.CancellationError.

You need to change the structure of the code, like this

then(function(..) {
    ...
})
.cancellable()
.catch(Promise.CancellationError, function (err) {
    ...
});

Note: I would recommend promising with its beautiful Promise constructor function. It is similar to the ECMA Script 6 specification.

new Promise(function(resolve, reject) {
    ...
});