0

With the following code, I'd expect task "asyncfail" to cause some error output to go to the console and for the exit code to be non-zero (just as there is for task "syncfail"). What actually happens though is that jake finishes without further output (sample output below) and the process exit code indicates success. I'm not sure if I'm doing something wrong with jake, or promises... Any ideas?

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;
}

Here is some sample output from task syncfail (which finishes as I'd expect) and asyncfail (which does not finish as I'd expect):

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
4

1 回答 1

1

The reason fail() was not working is that fail() works by throwing an exception to be caught at an outer layer, but that exception was being caught by the implementation of .then() instead. To make fail() work as expected while using promises in this way, I needed to wrap the call to fail() in setTimeout to re-throw the error outside the .then() handler.

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);
  }
}
于 2013-05-29T23:28:50.683 回答