在 promisifyAll 创建的 then 链中使用 cancel() [英] Use cancel() inside a then-chain created by promisifyAll

查看:13
本文介绍了在 promisifyAll 创建的 then 链中使用 cancel()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不确定我是否对这个标题足够清楚,但假设我有一个名为 Foo 的类,其中包含 method1method2method3.我使用 promisifyAll 来保证它的方法.

Not sure if I'm clear enough with this title, but assume that I have a class called Foo with method1, method2 and method3. I promisify its methods with promisifyAll.

然后我有一个 then 链,我想在第二个或第一个 then 中间取消操作,并且不应再调用 then.

Then I have a then-chain and I want to cancel the operation in the middle of the second or first then, and no further then should be called.

我阅读了有关取消的信息(http://bluebirdjs.com/docs/api/cancellation.html) 但我不知道如何使用 promisifyAll 实现它.

I read about Cancellation (http://bluebirdjs.com/docs/api/cancellation.html) but I don't know how to implement it with promisifyAll.

我得到的代码加上我需要的:

The code I got plus what I need:

var bluebird = require('bluebird');

function Foo() { }

Foo.prototype.method1 = function (cb) {};

Foo.prototype.method2 = function (cb) {};

Foo.prototype.method3 = function (cb) {};

var foo = bluebird.promisifyAll(new Foo());

foo.method1Async()
.then(function (r1) {
  // cancel then-chain
  res.json("Task stopped");
  // just stop right here
  promises.cancel();
})
.then(function (r2) {
  console.log(r2);
}).then(function (r3) {
  console.log(r3);
})
.catch(function (er) {
  console.log('Catch!');
});

得到这个结果的正确方法是什么?我知道我可以抛出一些东西并在 catch 方法中捕获它,但这会对我的实际代码产生很大的变化.

What is the proper way of having this result? I know I can just throw something and catch it in the catch method, but this would make a very big change in my real code.

推荐答案

试试这个:

var bluebird = require('bluebird');

function Foo() { }

Foo.prototype.method1 = function (cb) { cb(null, 'method1'); };
Foo.prototype.method2 = function (cb) { cb(null, 'method2'); };
Foo.prototype.method3 = function (cb) { cb(null, 'method3'); };

var foo = bluebird.promisifyAll(new Foo());

foo.method1Async()
.then(function (r1) {
  console.log('step 1');
  // cancel then-chain
  console.log("Task stopped");
  // just stop right here
  return bluebird.reject('some reason');
})
.then(function (r2) {
  console.log('step 2');
  console.log(r2);
}).then(function (r3) {
  console.log('step 3');
  console.log(r3);
})
.catch(function (er) {
  console.log('Catch!');
  console.log('Error:', er);
});

代替:

  return bluebird.reject('some reason');

你可以使用:

  throw 'some reason';

结果是一样的,但你不想抛出错误,所以你可以返回一个被拒绝的承诺.

and the result would be the same but you didn't want to throw errors so you can return a rejected promise instead.

但是,如果您打算连续运行所有 3 个方法,那么您还需要在每一步返回下一个承诺,如下所示:

But if your intention is to run all 3 methods in series then you will also need to return the next promise at each step with something like this:

var bluebird = require('bluebird');

function Foo() { }

Foo.prototype.method1 = function (cb) { cb(null, 'method1'); };
Foo.prototype.method2 = function (cb) { cb(null, 'method2'); };
Foo.prototype.method3 = function (cb) { cb(null, 'method3'); };

var foo = bluebird.promisifyAll(new Foo());

foo.method1Async()
.then(function (r1) {
  console.log('step 1');
  console.log('got value:', r1);
  // cancel? change to true:
  var cancel = false;
  if (cancel) {
    console.log("Task stopped");
    return bluebird.reject('some reason');
  } else {
    console.log('Keep going');
    return foo.method2Async();
  }
})
.then(function (r2) {
  console.log('step 2');
  console.log('got value:', r2);
  return foo.method3Async();
}).then(function (r3) {
  console.log('step 3');
  console.log('got value:', r3);
})
.catch(function (er) {
  console.log('Catch!');
  console.log('Error:', er);
});

目前,您问题中的代码永远不会运行除第一个方法之外的任何其他方法.

Currently the code in your question would never run any other method than the first one.

另一个不调用最后一个 catch 的例子:

Another example that doesn't call the last catch for that case:

foo.method1Async()
.then(function (r1) {
  console.log('step 1');
  console.log('got value:', r1);
  // cancel? change to true:
  var cancel = true;
  if (cancel) {
    console.log("Task stopped");
    return bluebird.reject('some reason');
  } else {
    console.log('Keep going');
    return foo.method2Async();
  }
})
.then(function (r2) {
  console.log('step 2');
  console.log('got value:', r2);
  return foo.method3Async();
}).then(function (r3) {
  console.log('step 3');
  console.log('got value:', r3);
})
.catch(function (er) {
  if (er === 'some reason') {
    return bluebird.resolve('ok');
  } else {
    return bluebird.reject(er);
  }
})
.catch(function (er) {
  console.log('Catch!');
  console.log('Error:', er);
});

说明

这样想:在同步代码中,如果你有:

Explanation

Think of it this way: in synchronous code if you had:

r1 = fun1();
r2 = fun2();
r3 = fun3();

那么fun1取消fun2和fun3执行的唯一方法就是抛出异常.与承诺类似,一个 then 处理程序可以取消下一个 then 处理程序的执行的唯一方法是返回一个被拒绝的承诺.就像同步代码抛出的异常会被 catch 块捕获一样,这里被拒绝的承诺将被传递给 catch 处理程序.

then the only way for fun1 to cancel the execution of fun2 and fun3 would be to throw an exception. And similarly for promises, the only way that one then handler could cancel the execution of the next then handler is to return a rejected promise. And just like with synchronous code that thrown exception would be caught by the catch block, here that rejected promise would be passed to the catch handler.

使用同步代码,您可以拥有一个内部 try/catch 来捕获异常并在它不是您用来取消执行的特定异常时重新抛出它.使用 promises,你可以有一个早期的 catch 处理程序,它的作用基本相同.

With synchronous code you can have an internal try/catch that catches the exception and rethrows it if it isn't the specific one that you used to cancel your execution. With promises you can have an earlier catch handler that does essentially the same.

这是更新 2 中的代码发生的情况.拒绝原因与某个值进行比较(在该示例中为 'some reason'),如果相等,则已解决的承诺是返回,因此不调用下一个 catch 处理程序.如果它不相等,则拒绝原因再次返回,因为被拒绝的承诺女巫然后作为真正的"错误传递给下一个 catch 处理程序,您希望最后一个 catch 处理程序.

This is what happens with the code in Update 2. The rejection reason is compared to some value (which is 'some reason' in that example) and if it is equal then a resolved promise is returned and so the next catch handler is not called. If it is not equal then the rejection reason is returned again as a rejected promise witch is then passed to the next catch handler as a "real" error that you want that last catch handler to handle.

这篇关于在 promisifyAll 创建的 then 链中使用 cancel()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆