使用 Q.deferred 捕获错误

Catching errors with Q.deferred

我有一个 nodeJS 项目,我希望在其中使用异步函数。也就是说,我正在使用 Q 库。

我有一个名为 someFunction() 的函数,我希望 return 一个承诺。使用 then -函数,我可以像这样检查承诺是否已解决或被拒绝:

    someFunction()
    .then(
      function(results) {
        console.log("Success!");
      },
      function (error) {
        console.log("An error occurred, and I would wish to log it for example");
      }
    );

我对上述函数的直觉期望是,错误函数会捕获所有可能的错误。因此,如果在 someFunction 内部引发了一些异常,我可以放心,错误函数将是 运行('then' 之后的第二个函数)。但好像不是这样。

例如,假设 someFunction 定义如下:

function someFunction() {
  var deferred = Q.defer();
  throw new Error("Can't bar.");

  deferred.resolve("success");
}

现在,如果我像上面代码块中那样调用函数 someFunction(),它不会 运行 错误函数。这是为什么? promise Q.deferred 的偏点不是用来捕获错误的吗?为什么我要手动拒绝发生的每个错误?我知道我可以将 someFunction 的全部内容设置为 try/catch 子句,然后拒绝 deferred,但这感觉太不对了!一定有更好的方法,我相信你们中的一些人知道!

有了这些信息,我开始思考 deferred.reject 和 deferred.resolve 到底应该用在什么地方?它甚至意味着捕捉异常吗?我真的应该手动检查所有错误情况,然后对它们调用 deferred.reject 吗?我很想知道这应该如何专业地处理。

Q 有特定的成功和错误函数,所以使用:

deferred.reject("error");

而不是抛出异常。

接下来是 someFunction 必须 return 承诺在您使用它时使用它:

function someFunction() {

  var deferred = Q.defer();

  try{

  //some Asynchronous code
  deferred.resolve("success");


  }catch(e){

    deferred.reject(e.message);

  }

  return deffered.promise; //return promise to use then
}

抛出错误将停止代码执行(并关闭节点),除非您在 try/catch 块中捕获错误。

来自请求的已处理错误可以通过使用 deferred.reject(error) 传递到 .catch 链。代码错误和自定义抛出的错误需要在try/catch内部处理,这才是处理此类错误的正确方法。

function someFunction() {
  var deferred = Q.defer();
  deferred.reject("Can't bar.");
  // or
  try {
    throw new Error("Can't bar.");
  }
  catch(err) {
    deferred.reject("Can't bar.");
  }

  deferred.resolve("success");
}

因为 Promise 不是魔法。他们不会以某种方式神奇地捕捉到错误。他们抓住了他们,因为他们将对回调的调用包装在 try..catch-blocks 中,以将错误转换为被拒绝的承诺。

如果您希望 Promise 链处理错误,请将函数调用放入 Promise 链中:Q.resolve().then(someFunction).then(...)。 现在 someFunction 中发生的任何同步错误都可以在下面的 then 中处理。

顺便说一句:如果您使用 Q.defer(),并且您没有处理某些回调样式 API,那么您的做法肯定是错误的。搜索延迟反模式。

it won't run the error function. Why is that?

因为你同步抛出了一个异常,而不是返回一个 promise。 Which you never should.

Isn't the partial point of the promise Q.deferred to catch errors?

没有。 thencatch 在它们的回调中隐式地捕获异常,defferreds 不会 - 它们只是一个 () API 来创建承诺。

Why should I manually reject every error that happens?

因为异步错误无论如何都应该传递给回调,而不是被抛出。

I know I could set the whole content of someFunction to try/catch clause, and then reject the deferred, but that feels so wrong! There must be a better way!

有:Q.Promise constructor,标准 (ES6) promise 创建 API。它的好处是能够从执行程序函数中捕获同步异常:

function someFunction() {
  return new Q.Promise(function(resolve) {
    throw new Error("Can't bar.");
    resolve("success");
  });
}