在promisifyAll创build的then-chain链中使用cancel()
不知道我是否足够清楚这个标题,但假设我有一个名为Foo的类与方法1,方法2和方法method3
。 我promisifyAll与promisifyAll
方法。
然后,我有一个时间链,我想在第二个或第一个中间取消操作,那么不应该再叫。
我读了取消( http://bluebirdjs.com/docs/api/cancellation.html ),但我不知道如何与promisifyAll实施。
我得到的代码加上我所需要的:
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
方法中捕获它,但是这会对我的真实代码做出很大的改变。
尝试这样的事情:
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';
结果将是相同的,但你不想抛出错误,所以你可以返回一个被拒绝的承诺。
更新1
但是,如果你的目的是要连续运行所有3种方法,那么你还需要在每一步中返回下一个承诺,如下所示:
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); });
目前在你的问题代码将永远不会运行任何其他方法比第一个。
更新2
另一个例子,并没有调用最后一个catch
的情况:
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); });
说明
这样想:在同步代码,如果你有:
r1 = fun1(); r2 = fun2(); r3 = fun3();
那么fun1取消fun2和fun3执行的唯一方法就是抛出一个exception。 对于承诺也是如此,那么一个处理程序可以取消下一个处理程序的执行的唯一方法就是返回一个被拒绝的承诺。 就像catch
块抛出exception的同步代码一样,在这里被拒绝的promise将被传递给catch
处理程序。
使用同步代码,你可以有一个内部的try/catch
捕获exception,如果它不是你用来取消执行的那个exception,就会重新抛出exception。 有了承诺,你可以有一个早期的catch
处理程序,基本上是一样的。
这是更新2中的代码所发生的情况。拒绝原因与某个值(在该示例中是'some reason'
)进行比较,如果相等则返回已parsing的promise,因此不调用下一个catch
处理程序。 如果不相等,拒绝原因再次返回,因为被拒绝的承诺女巫然后被传递给下一个catch
处理程序,作为您想要最后一个catch
处理程序处理的“真实”错误。