使用以下代码,我希望任务“asyncfail”导致一些错误输出转到控制台,退出代码非零(就像任务“syncfail”一样)。实际发生的事情是jake没有进一步的输出(下面的示例输出)完成,并且进程退出代码表示成功。我不确定我是否对杰克或承诺做错了什么......有什么想法吗?
var Q = require("q");
task("syncfail", function() {
fail("synchronous failure");
});
var http = require("http");
task("asyncfail", function() {
waitForSleep().then(waitForSleep).then(waitForSleep).then(waitForSleep).then(function() {
console.log("all done, time to fail");
fail("This is the end");
});
console.log("finishing sync part");
}, { async:true});
function waitForSleep() {
var deferred = Q.defer();
setTimeout(function() {
console.log("finished timeout");
deferred.resolve();
});
return deferred.promise;
}
以下是来自任务syncfail的一些示例输出(按照我的预期完成)和asyncfail(它没有像我期望的那样完成):
C:\src\letscodejavascript>node node_modules\jake\bin\cli.js -f .\jakerepro.js syncfail
jake aborted.
Error: synchronous failure
at api.fail (C:\src\letscodejavascript\node_modules\jake\lib\api.js:221:18)
(See full trace by running task with --trace)
C:\src\letscodejavascript [master]> $lastexitcode
1
C:\src\letscodejavascript [master]> .\jake.bat -f .\jakerepro.js asyncfail
C:\src\letscodejavascript>node node_modules\jake\bin\cli.js -f .\jakerepro.js asyncfail
finishing sync part
finished timeout
finished timeout
finished timeout
finished timeout
all done, time to fail
C:\src\letscodejavascript [master]> $lastexitcode
0
答案 0 :(得分:1)
fail()失败的原因是fail()通过抛出异常来捕获外层,但异常被.then()的实现捕获。为了使fail()在以这种方式使用promise时按预期工作,我需要在setTimeout中调用fail()来重新抛出.then()处理程序之外的错误。
var Q = require("q");
task("asyncfail", function() {
waitForSleepPromise()
.then(waitForSleepPromise)
.then(waitForSleepPromise)
.then(waitForSleepPromise)
.then(function() {
console.log("all done, time to fail");
deferError(function() {
fail("This is the end", "fasdf");
});
});
console.log("finishing sync part");
}, { async:true});
function waitForSleepPromise() {
var deferred = Q.defer();
setTimeout(function() {
console.log("finished timeout");
deferred.resolve();
}, 10);
return deferred.promise;
}
function deferError(callback) {
try {
callback();
}
catch (err){
setTimeout(function() {
throw err;
}, 0);
}
}