在node.js中使用q时如何删除样板代码



我当前正在将q与Node.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;
}

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

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

是的,Q有专门的帮助器功能用于与节点回调接口。

您可以将代码简化为

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有下面的内置版本,所以如果您使用Q(就像OP一样),请参阅Bergi的答案。如果您正在使用其他promise lib,请查看它是否使用;如果没有,请参见下文。

<小时>

您可以为自己提供一个实用函数,该函数封装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拒绝promise,要么使用在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)
}

相关内容

  • 没有找到相关文章

最新更新