2015-10-27 1 views
4

В настоящее время я использую q с Node.js. Все мои модели используют обещания от q. Позже я понял, написав много шаблонов, таких какКак удалить код шаблона при использовании q в node.js

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; 
} 

Есть ли способ удалить этот шаблонный код?

+0

Вы можете предоставить образец 'User.count' и' User.find'? – Grundy

+0

@Grundy, я использую mongoose, поэтому они являются стандартными методами модели mongoose. – Rahul

+0

похоже на мангустский инструмент, используя обещания: http://mongoosejs.com/docs/api.html#promise_Promise – Grundy

ответ

4

Есть ли способ удалить этот шаблонный код?

Да, 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, {}) 

Но обратите внимание, что с этими решениями вы должны убедиться, что count и findAll вызываются с нулевыми аргументами.

+0

I * должен был знать, что Q будет иметь эти. :-) –

+1

@Bergi: «Но обратите внимание, что с помощью этих решений вам нужно обеспечить, чтобы count и findAll вызывались с нулевыми аргументами». Не могли бы вы объяснить это? – espeirasbora

+0

@Bergi, Все, кроме 'Q.ninvoke', не дает мне результата. – Rahul

2

Примечание: Q имеет встроенную версию ниже, поэтому, если вы используете Q (как OP), см. Bergi's answer. Если вы используете другое обещание 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. Может использоваться со всеми функциями типа Node, вызывающими их обратные вызовы с err в качестве первого аргумента.

Но, кто-то уже сделал это для вас: 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) 
} 
Смежные вопросы