蓝鸟 Promise 取消

3

假设我有以下的Promise链:

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();

以上代码永远不会进入catch块。

如果我们将condition交换为true,则内部取消将永远不会触发,但catch仍不会被触发。

去掉结尾处的.cancellable,并将所有实例的parentPromise.cancel()替换为显式的throw new Promise.CancellationError() “修复”了这个问题。我不理解的是为什么?

为什么原始方法不起作用?

我正在使用bluebird 2.3.11。


我认为你必须首先使承诺可取消,而不是最后。 - Tomalak
Tomalak 是正确的,你只是使 .catch() 返回的 Promise 可取消。父级无法事后从其子级继承可取消性,但子级将从其父级继承可取消性。 - Esailija
1个回答

3

cancellable() 创建可取消的 Promise,只有在未经任何原因调用 cancel 函数时才会默认抛出 CancellationError 异常。

在您的情况下,您在附加 catch 处理程序之后才使 Promise 成为可取消状态。但是 Promise 还没有变成可取消状态。因此,调用 cancel 函数不会引发 Promise.CancellationError 异常。

您需要改变代码结构,像这样:

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

注意:我建议使用美丽的Promise构造函数来实现。它类似于ECMA Script 6规范。

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

当我尝试在我的.catch()之前使用.cancellable()来引入promise时,服务器永远不会启动... - Abraham P
@AbrahamP 请确保在.cancellable后面删除;。如果这不是问题,请展示当前的代码。 - thefourtheye
当前代码: https://github.com/apolishch/bookshelf-soft-delete/blob/master/index.js对于错误情况,请将第20行和第26行替换为return parentPromise.cancel(),并在第30行和第31行之间添加一行只包含.cancellable的代码。 - Abraham P
@AbrahamP 很抱歉,如果你能提供一个SSCCE会更好。 - thefourtheye
@AbrahamP 这是一个简单的工作取消示例:https://gist.github.com/troygoode/cb82991c71eafa0c7323 - Troy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接