【问题标题】:How to remove the boilerplate code when using q in node.js在 node.js 中使用 q 时如何删除样板代码
【发布时间】:2015-10-27 07:51:39
【问题描述】:

我目前正在使用qNode.js。我所有的模型都使用来自q 的承诺。后来我意识到写了很多这样的样板代码

count: function(){
  var deferred = Q.defer()
  User.count(function(err,count){
    if(err)
      deferred.reject(err)
    else
      deferred.resolve(count)
  })
  return deferred.promise;
},
findAll: function(){
  var deferred = Q.defer()
  User.find({}, function(err,users){
    if(err)
      deferred.reject(err)
    else
      deferred.resolve(users)
  })
  return deferred.promise;
}

有没有办法删除这个样板代码?

【问题讨论】:

标签: javascript node.js q boilerplate


【解决方案1】:

有没有办法删除这个样板代码?

是的,Q 有dedicated helper functions for interfacing with node callbacks

您可以将代码简化为

count: function(){
  return Q.nfcall(User.count);
},
findAll: function(){
  return Q.nfcall(User.find, {});
}

如果这些方法依赖于它们的this 值,您可以使用Q.ninvoke(User, "count")Q.ninvoke(User, "find", {})

你甚至可以更进一步,完全避免函数表达式,通过使用 Q 的函数/方法绑定:

count: Q.nfbind(User.count),
findAll: Q.nfbind(User.find, {})

或带有this 值:

count: Q.nbind(User.count, User),
findAll: Q.nbind(User.find, User, {})

但请注意,使用这些解决方案时,您需要确保使用零参数调用 countfindAll

【讨论】:

  • 应该知道 Q会有这些。 :-)
  • @Bergi,“但请注意,使用这些解决方案,您需要确保使用零参数调用 count 和 findAll”。你能解释一下吗?
  • @Bergi,Q.ninvoke 以外的所有内容都没有给我结果。
  • @espeirasbora:当您“绑定”函数并调用findAll(x, y) 时,Q 将调用User.find({}, x, y, function(err, res) {…}) - 这是行不通的。所以你总是只能打电话给findAll()
【解决方案2】:

注意: Q 具有以下的内置版本,因此如果您使用 Q(就像 OP 一样),请参阅 Bergi's answer。如果您正在使用其他一些承诺库,请查看是否可以;如果没有,请参见下文。


你可以给自己一个实用函数来包装 Node 风格的调用并将它们转换为 Promise(但请继续阅读),所以:

count: function() {
  return makePromise(User.count)
}

makePromise 看起来像

function makePromise(f) {
  var deferred = Q.defer()
  var args = Array.prototype.slice.call(arguments)
  args[0] = function(err) {
    if(err)
      deferred.reject(err)
    else
      deferred.resolve(Array.prototype.slice.call(arguments, 1))
  }
  f.apply(null, args)
  return deferred.promise
}

(我正在尝试遵循您的约定,即 ASI 会更正 ;

它调用你给它的函数,传递任何进一步的参数,当它得到响应时,要么使用err 拒绝承诺,要么使用它在err 之后得到的参数数组来解决它。可以与所有以err 作为第一个参数调用其回调的 Node 样式函数一起使用。

但是,有人已经为你做到了:promisify :-) 我很确定至少还有一个。

稍微复杂一点的版本将支持可选地预先提供thisArg

function makePromise(obj, f) {
  var deferred = Q.defer()
  var args, func, thisArg;
  if (typeof obj === "function") {
    thisArg = null
    func = obj
    args = Array.prototype.slice.call(arguments)
  } else {
    thisArg = obj
    func = f
    args = Array.prototype.slice.call(arguments, 1)
  }
  args[0] = function(err) {
    if(err)
      deferred.reject(err)
    else
      deferred.resolve(Array.prototype.slice.call(arguments, 1))
  }
  func.apply(thisArg, args)
  return deferred.promise
}

那么如果User.count需要用this调用=User:

count: function() {
  return makePromise(User, User.count)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 2014-05-05
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    相关资源
    最近更新 更多