在由 promisifyAll 创建的 then-chain 中使用 cancel()
Use cancel() inside a then-chain created by promisifyAll
不确定我是否对这个标题足够清楚,但假设我有一个名为 Foo 的 class 以及 method1
、method2
和 method3
。我用 promisifyAll
.
承诺它的方法
然后我有一个then-chain,我想在第二个或第一个then的中间取消操作,然后不再调用。
我阅读了有关取消 (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';
结果是一样的,但你不想抛出错误,所以你可以 return 一个被拒绝的承诺。
更新 1
但是,如果您打算 运行 串联所有 3 种方法,那么您还需要 return 在每个步骤的下一个承诺,如下所示:
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执行的唯一方法就是抛出异常。与承诺类似,一个 then
处理程序可以取消下一个 then
处理程序执行的唯一方法是 return 拒绝承诺。就像抛出异常的同步代码会被 catch
块捕获一样,这里被拒绝的承诺将被传递给 catch
处理程序。
使用同步代码,您可以有一个内部 try/catch
捕获异常并重新抛出它(如果它不是您用来取消执行的特定异常)。使用 promises,您可以拥有一个更早的 catch
处理程序,其功能基本相同。
这就是更新 2 中的代码所发生的情况。将拒绝原因与某个值(在该示例中为 'some reason'
)进行比较,如果相等,则已解决的承诺为 returned,因此不会调用下一个 catch
处理程序。如果不相等,则拒绝原因再次被 return 编辑为被拒绝的承诺 然后作为您想要的 "real" 错误传递给下一个 catch
处理程序要处理的最后 catch
个处理程序。
不确定我是否对这个标题足够清楚,但假设我有一个名为 Foo 的 class 以及 method1
、method2
和 method3
。我用 promisifyAll
.
然后我有一个then-chain,我想在第二个或第一个then的中间取消操作,然后不再调用。
我阅读了有关取消 (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';
结果是一样的,但你不想抛出错误,所以你可以 return 一个被拒绝的承诺。
更新 1
但是,如果您打算 运行 串联所有 3 种方法,那么您还需要 return 在每个步骤的下一个承诺,如下所示:
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执行的唯一方法就是抛出异常。与承诺类似,一个 then
处理程序可以取消下一个 then
处理程序执行的唯一方法是 return 拒绝承诺。就像抛出异常的同步代码会被 catch
块捕获一样,这里被拒绝的承诺将被传递给 catch
处理程序。
使用同步代码,您可以有一个内部 try/catch
捕获异常并重新抛出它(如果它不是您用来取消执行的特定异常)。使用 promises,您可以拥有一个更早的 catch
处理程序,其功能基本相同。
这就是更新 2 中的代码所发生的情况。将拒绝原因与某个值(在该示例中为 'some reason'
)进行比较,如果相等,则已解决的承诺为 returned,因此不会调用下一个 catch
处理程序。如果不相等,则拒绝原因再次被 return 编辑为被拒绝的承诺 然后作为您想要的 "real" 错误传递给下一个 catch
处理程序要处理的最后 catch
个处理程序。