具有异步故障的jake任务不会导致故障通知冒泡

时间:2013-05-27 23:07:38

标签: node.js promise jake

使用以下代码,我希望任务“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

1 个答案:

答案 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);
  }
}