在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有专门的辅助函数用于连接节点callback 。
你可以简化你的代码
count: function(){ return Q.nfcall(User.count); }, findAll: function(){ return Q.nfcall(User.find, {}); }
如果这些方法依赖于this
值,可以使用Q.ninvoke(User, "count")
和Q.ninvoke(User, "find", {})
。
你甚至可以通过使用Q的函数/方法绑定,把它提高到一个更高的极限,完全避免函数expression式:
count: Q.nfbind(User.count), findAll: Q.nfbind(User.find, {})
或用this
值:
count: Q.nbind(User.count, User), findAll: Q.nbind(User.find, User, {})
但请注意,通过这些解决scheme,您需要确保使用零参数调用count
和findAll
。
注意: Q有一个下面的内置版本,所以如果你使用Q(作为OP),请参阅Bergi的答案 。 如果你正在使用其他的promise lib,看看是否可以; 如果没有,请参阅下文。
你可以给自己一个包装Node风格调用的实用函数,并把它们变成承诺(但是不断阅读),所以:
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
之后获得的参数数组来解决它。 可以与所有调用其callback函数的所有Nodetypes的函数一起使用,作为第一个参数。
但是 ,有人已经为你做了这样的事情: promisify
:-)我相当肯定至less还有另外一个。
稍微复杂一点的版本可以支持可选地给一个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) }