2

我有一个可以取消的蓝鸟承诺。取消后,我必须做一些工作才能巧妙地中止正在运行的任务。可以通过两种方式取消任务:通过promise.cancel()promise.timeout(delay)

为了能够在取消或超时时巧妙地中止任务,我必须捕获 CancellationErrors 和 TimeoutErrors。捕获 CancellationError 有效,但由于某种原因我无法捕获 TimeoutError:

var Promise = require('bluebird');

function task() {
  return new Promise(function (resolve, reject) {
        // ... a long running task ...
      })
      .cancellable()
      .catch(Promise.CancellationError, function(error) {
        // ... must neatly abort the task ...
        console.log('Task cancelled', error);
      })
      .catch(Promise.TimeoutError, function(error) {
        // ... must neatly abort the task ...
        console.log('Task timed out', error);
      });
}

var promise = task();

//promise.cancel(); // this works fine, CancellationError is caught

promise.timeout(1000); // PROBLEM: this TimeoutError isn't caught!

如何在设置超时之前捕获超时错误?

4

1 回答 1

5

当你取消一个 promise 时,只要发现仍然可以取消的父级,取消首先会向它的父级冒泡,这与仅传播给子级的正常拒绝有很大不同。

.timeout做一个简单的正常拒绝,它不做取消,所以这就是为什么不可能这样做。

您可以在延迟后取消:

var promise = task();
Promise.delay(1000).then(function() { promise.cancel(); });

或者在任务函数中设置超时时间:

var promise = task(1000);

function task(timeout) {
  return new Promise(function (resolve, reject) {
        // ... a long running task ...
      })
      .timeout(timeout)
      .cancellable()
      .catch(Promise.CancellationError, function(error) {
        // ... must neatly abort the task ...
        console.log('Task cancelled', error);
      })
      .catch(Promise.TimeoutError, function(error) {
        // ... must neatly abort the task ...
        console.log('Task timed out', error);
      });
}

您还可以创建一个方法,如:

Promise.prototype.cancelAfter = function(ms) {
  var self = this;
  setTimeout(function() {
    self.cancel();
  }, ms);
  return this;
};

然后

function task() {
  return new Promise(function (resolve, reject) {
        // ... a long running task ...
      })
      .cancellable()
      .catch(Promise.CancellationError, function(error) {
        // ... must neatly abort the task ...
        console.log('Task cancelled', error);
      })
}

var promise = task();

// Since it's a cancellation, it will propagate upwards so you can
// clean up in the task function
promise.cancelAfter(1000);
于 2014-05-08T10:02:59.717 回答