如何使用 Q 正确中止 node.js 承诺链?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11302271/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to properly abort a node.js promise chain using Q?
提问by Zane Claes
I'm using the Q modulefor Node.js in attempts to avoid the "pyramid of doom" in scenarios where I have many steps. For example:
我正在使用Node.js的 Q 模块,试图在我有很多步骤的情况下避免“末日金字塔”。例如:
function doTask(task, callback)
{
Q.ncall(task.step1, task)
.then(function(result1){
return Q.ncall(task.step2, task);
})
.then(function(result2){
return Q.ncall(task.step3, task);
})
.fail(callback).end();
}
Essentially this seems to work; if an error is thrown by any of the task steps, it is passed to the callback (though I would be welcome to improvements, as I am new to node.js promises). However, I have a problem when I need to abort the task-chain early. For example, if result1 is successfully returned I might want to call the callback early and abort the rest, but my attempts to do so are failing...
基本上这似乎有效;如果任何任务步骤抛出错误,则将其传递给回调(尽管我欢迎改进,因为我是 node.js 承诺的新手)。但是,当我需要提前中止任务链时,我遇到了问题。例如,如果 result1 成功返回,我可能想提前调用回调并中止其余的,但我这样做的尝试失败了......
function doTask(task, callback)
{
Q.ncall(task.step1, task)
.then(function(result1){
if(result1)
{// the rest of the task chain is unnecessary
console.log('aborting!');
callback(null, result1);
return null;
}
return Q.ncall(task.step2, task);
})
.then(function(result2){
console.log('doing step 3...');
return Q.ncall(task.step3, task);
})
.fail(callback).end();
}
In this example, I see both "aborting!" and "doing step 3..." printed.
在这个例子中,我看到了“正在中止!” 并打印“执行第 3 步...”。
I'm sure I'm merely misunderstanding some basic principles here, so would appreciate any help. Thanks!
我确定我只是误解了这里的一些基本原则,因此希望得到任何帮助。谢谢!
采纳答案by Calvin Alvin
Any errors that are thrown within the promise chain will cause the entire stack to be aborted early and control is given to the error-back path. (in this case, the fail() handler) When you detect a certain state which causes you to want to abort the promise chain, then just throw a very specific error, which you trap in the error-back and ignore (if you so choose)
在 promise 链中抛出的任何错误都将导致整个堆栈提前中止,并将控制权交给错误返回路径。(在这种情况下,fail() 处理程序)当您检测到某个状态导致您想要中止承诺链时,只需抛出一个非常具体的错误,您将其捕获在错误返回中并忽略(如果您这样做)选择)
function doTask(task, callback)
{
Q.ncall(task.step1, task)
.then(function(result1){
if(result1 == 'some failure state I want to cause abortion')
{// the rest of the task chain is unnecessary
console.log('aborting!');
throw new Error('abort promise chain');
return null;
}
return Q.ncall(task.step2, task);
})
.then(function(result2){
console.log('doing step 3...');
return Q.ncall(task.step3, task);
})
.fail(function(err) {
if (err.message === 'abort promise chain') {
// just swallow error because chain was intentionally aborted
}
else {
// else let the error bubble up because it's coming from somewhere else
throw err;
}
})
.end();
}
回答by Kris Kowal
This is a case where you will need to branch, which does mean either nesting or creating a subroutine.
在这种情况下,您需要分支,这意味着嵌套或创建子例程。
function doTask(task, callback) {
return Q.ncall(task.step1, task)
.then(function(result1) {
if (result1) return result1;
return Q.ncall(task.step2, task)
.then(function(result2) {
return Q.ncall(task.step3, task);
})
})
.nodeify(callback)
}
Or
或者
function doTask(task, callback) {
return Q.ncall(task.step1, task)
.then(function(result1) {
if (result1) {
return result1;
} else {
return continueTasks(task);
}
})
.nodeify(callback)
}
function continueTasks(task) {
return Q.ncall(task.step2, task)
.then(function(result2) {
return Q.ncall(task.step3, task);
})
}
回答by George
I believe you only have to reject the promise to break out of the promise chain.
我相信你只需要拒绝承诺就可以跳出承诺链。
https://github.com/kriskowal/q/wiki/API-Reference#qrejectreason
https://github.com/kriskowal/q/wiki/API-Reference#qrejectreason
also it seems like .end() has been changed to .done()
似乎 .end() 也已更改为 .done()
function doTask(task, callback)
{
Q.ncall(task.step1, task)
.then(function(result1){
if(result1)
{// the rest of the task chain is unnecessary
console.log('aborting!');
// by calling Q.reject, your second .then is skipped,
// only the .fail is executed.
// result1 will be passed to your callback in the .fail call
return Q.reject(result1);
}
return Q.ncall(task.step2, task);
})
.then(function(result2){
console.log('doing step 3...');
return Q.ncall(task.step3, task);
})
.fail(callback).done();
}

