我不确定我是否对此标题足够清楚,但假设我有一个名为Foo的课程method1
,method2
和method3
。我用promisifyAll
来宣传它的方法。
然后我有一个then-chain,我想在第二个或第一个中间取消操作,然后不应再调用。
我读过有关取消(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
方法中抛出一些内容并将其捕获,但这会对我的实际代码产生很大的影响。
答案 0 :(得分:1)
尝试这样的事情:
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';
并且结果会相同,但您不想抛出错误,因此您可以返回被拒绝的承诺。
但是如果你打算连续运行所有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);
});
目前,您问题中的代码永远不会运行除第一个之外的任何其他方法。
另一个不为该案例调用最后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执行的唯一方法就是抛出异常。类似地,对于promises,一个then
处理程序可以取消执行下一个then
处理程序的唯一方法是返回被拒绝的promise。就像使用同步代码一样,抛出异常将被catch
块捕获,这里被拒绝的promise将被传递给catch
处理程序。
使用同步代码,您可以拥有一个内部try/catch
来捕获异常,如果它不是您用来取消执行的特定代码,则重新抛出异常。使用promise,您可以拥有一个基本相同的catch
处理程序。
这是Update 2中的代码所发生的情况。将拒绝原因与某个值(在该示例中为'some reason'
)进行比较,如果它相等,则返回已解析的promise,因此下一个{ {1}}处理程序未被调用。如果它不相等,那么拒绝原因将再次返回,因为被拒绝的promise将被传递给下一个catch
处理程序,作为您希望最后catch
处理程序处理的“真正”错误。 / p>