javascript - Q promise 传播错误和异常

标签 javascript node.js error-handling q

我正在使用此代码将经典的 nodejs 函数转换为 promise 函数:

  Object.defineProperty(Function.prototype, "toPromise", {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function(self) {
      var $this;
      $this = this;
      return function() {
        var arg, args, deferred, _i, _len;
        deferred = Q.defer();
        args = [];
        for (_i = 0, _len = arguments.length; _i < _len; _i++) {
          arg = arguments[_i];
          args.push(arg);
        }
        args.push(function() {
          args = Array.prototype.slice.call(arguments);
          if (args[0] instanceof Error) {
            return deferred.reject.apply($this, args);
          } else {
            return deferred.resolve.apply($this, args);
          }
        });
        $this.apply(self, args);
        return deferred.promise;
      };
    }
  });

然后我在一个函数上调用它以获取另一个函数。像那样:

  exports.list = (function(userid, options, callback) {
    // do something 
    // success ->
        callback(data);
    // error ->
        callback(err)
  }).toPromise(this);

但是当抛出不是我抛出的异常(SyntaxError、TypeError...)时,thenfail 函数不是叫。如何自动传播?

我试图用它替换 toPromise 但这没有用(即使它正在使用我的函数)

  Object.defineProperty(Function.prototype, "toPromise", {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function(self) {
      var $this;
      $this = this;
      return Q.denodeify(this.bind(Kitty));
    }
  });

我还尝试对 then 应用第二个回调,但我也没有成功。

最佳答案

But when an exception that wasn't thrown by me (SyntaxError, TypeError...) is thrown, the then or fail function isn't called.

Q 只捕获从 .then() 回调中抛出的异常。您需要自己明确处理所有其他异常。

How to propagate it automatically?

如果异常是从您自己的代码中抛出的,您可以考虑在较低级别使用 Promises,并将您自己的代码仅放在 then 回调中。

如果异常是从您调用的“经典 nodejs 函数”中抛出的,您将需要捕获它。但是,抛出异常(这是相当不可恢复的)而不是仅仅使用错误参数调用回调可能有充分的理由,这将是异步 Node 函数的“正常”设计方法。

如果你想在你的 toPromise 方法中包含这样的功能,它需要包装函数调用:

try {
  $this.apply(self, args);
} catch(e) {
  deferred.resolve(e);
}

(function(…, callback) { … }).toPromise(this);

这是个坏主意。你不应该在你自己的函数上使用 toPromise,而应该只在那些给你的并且有非 promise 接口(interface)的函数上使用。参见 The Beginning在教程部分如何提出一个真正返回 Promise 的函数。不要使用 callback 变量。一些错误很容易让你逃脱。特别是如果你有一个已经产生 promise 的函数,你需要做的就是在它之后链接其他任务。

在您的具体情况下,这很简单

exports.list = function(userid, options) {
  return canThis(userid, "mod", "browse").then(function(can) {
    if (can === false)
      throw error.throwError("Forbidden", "UNAUTHORIZED");
    if (options.perPage > 50) {
      throw error.throwError("Too much mods per page", "INVALID_PARAMS");

    var Mod = mongoose.model("Mod");
    return Q.all([ // I would assume that listing and counting can happen in parallel?
      Q.ninvoke(Mod, "list", options),
      Q.ninvoke(Mod.count(), "exec")
    ]).spread(function(mods, count) {
      mods.totalCount = count;
      return mods;
    }, function(err) { // and throw this error when one happens in either?
      throw error.throwError(err, "DATABASE_ERROR");
      // not sure whether you need errors.handleResult at all
      // (not with a callback, at least)
    });
  });
};

现在所有这些 return 实际上都有意义了。

关于javascript - Q promise 传播错误和异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23410273/

相关文章:

javascript - 我如何在Mac中处理此文件上传错误?

javascript - 如何将字符串值映射到 HTML id

javascript - VSCODE : No debug adapter, 无法发送 'variables' "

swift - Swift 2.0 do-try-catch 和常规 Java/C#/C++ 异常有什么区别

django - 在Django中使用try除外进行错误处理

javascript - 如果 Node 进程本身很忙会发生什么

javascript - 动态更改video.src HTML 5

javascript - 点击/关闭点击? JS 计时器?如何让每一个重复工作

javascript - 用类 'ul:first-child' 替换选择器 '.list_wrapper:first-child'

node.js - 如何隐藏nodemailer用于推送公共(public)github存储库的gmail密码?