在promisifyAll创建的then链中使用cancel() [英] Use cancel() inside a then-chain created by promisifyAll
问题描述
不确定我是否对这个标题足够清楚,但是假设我有一个名为Foo的类,其中包含method1
,method2
和method3
.我用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 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的唯一方法是引发异常.与promise类似,一个then
处理程序可以取消执行下一个then
处理程序的唯一方法是返回被拒绝的promise.就像使用同步代码一样,抛出异常的事件将被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
,该内部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.
这是Update 2中的代码发生的情况.拒绝原因与某个值(在该示例中为'some reason'
)进行比较,如果相等,则返回已解决的Promise,因此下一个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屋!