Задача jake с асинхронным отказом не вызывает всплывающее уведомление об ошибке
С помощью следующего кода я бы ожидал, что задача "asyncfail" вызовет вывод какой-либо ошибки на консоль и код выхода будет ненулевым (так же, как для задачи "syncfail"). Однако на самом деле происходит то, что Джейк заканчивает работу без дальнейшего вывода (пример вывода ниже), а код завершения процесса указывает на успех. Я не уверен, что я делаю что-то не так с Джейком или обещаниями... Есть идеи?
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
1 ответ
Причина, по которой fail () не работала, состоит в том, что fail () работает, генерируя исключение, которое будет перехвачено на внешнем уровне, но это исключение было перехвачено реализацией.then (). Чтобы заставить fail () работать должным образом при использовании обещаний таким образом, мне нужно было обернуть вызов метода fail () в setTimeout, чтобы повторно выдать ошибку за пределы обработчика.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);
}
}