【问题标题】:jake task with asynchronous failure is not causing a failure notification to bubble up具有异步失败的 jake 任务不会导致失败通知冒泡
【发布时间】:2013-05-30 08:23:54
【问题描述】:

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

【问题讨论】:

    标签: node.js promise jake


    【解决方案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);
      }
    }
    

    【讨论】:

    • 你也可以在你的承诺上调用 .done() 。 .done() 重新抛出任何未处理的错误,从而允许 jake 的处理程序做正确的事情。 fwiw,bluebird.js 不鼓励使用 .done() 虽然我对究竟为什么有点模糊。 o/ \o
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多