在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,您需要确保使用零参数调用countfindAll

注意: 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) } 
Interesting Posts