2014-04-01 13 views
11

Utilizzo di mangusta per interrogare i risultati di db e Q per le promesse, ma trovando difficile riuscire a capirmi solo ottenendo un elenco di utenti disponibili. Attualmente ho un po 'di qualcosa di simile:Mongoose e promesse: come ottenere una serie di risultati di query?

var checkForPerson = function(person) { 
    people = mongoose.model('Person', Person) 

    return people.findOne({"_id": person }, function(err, doc) { 
     if (err) console.log(err) 

     if (doc !== null) { 
      return doc 
     } else { 
      console.log('no results') 
     } 

    }) 
} 

var promises = someArrayOfIds.map(checkForPerson); 

// this is where I would like to have an array of models 
var users = Q.all(promises) 

//this fires off before the people.findOne query above to users is undefined 
SomeOtherFunction(users) 

Come potrei fare per avere le query terminano prima SomeOtherFunction senza fare tonnellate di callback sciatta?

risposta

18

Un altro suggerimento sarebbe quello di utilizzare l'operatore $in di MongoDB per passare una serie su find e ottenere un ampio set di risultati in modo efficiente. Ciascuno sarà un oggetto Mongoose.

var promise = people.find({ _id: { $in: someArrayOfIds }).exec(); 
promise.then(function(arrayOfPeople) { 
    // array of people ... do what you want here... 
}); 

Questo sarebbe molto più efficiente di fare richieste multiple, una per ogni _id.

+1

Non lo sapevo mai, $ in ', lo proverò sicuramente! –

+1

@delboud op se questa è la risposta che ha risolto il problema, dovresti considerare di accettarlo sul mio che hai appena accettato. In tutta onestà, mentre la mia risposta fornisce molto più background teorico e informazioni utili sulle promesse IMO - questa è la risposta pratica per le persone che affrontano questo problema in Mongoose. Puoi invitare la mia risposta se la trovi utile, ma io sono tutto per la soluzione pratica :) –

+1

In realtà stavo lottando con le promesse, quindi la tua ha risposto alla mia domanda, ma mi ha dato una visione di una funzionalità. Ad ogni modo con me :) –

5

La risposta alla domanda "come continuare con le promesse" è quasi sempre con .then. È l'analogia promessa di ; e termina un'istruzione asincrona. Puoi restituire le promesse e le scaccherà prima di continuare.

Q.all(promises).then(function(users){ 
    SomeOtherFunction(users); 
}); 

O semplicemente Q.all(promise).then(SomeOtherFunction)

Si sarebbe anche bisogno di findOne di tornare in realtà le promesse. È possibile utilizzare Q.nfcall che chiama una funzione di nodo o promisify it yourself.

Che cosa fa Q.all accetta una serie di promesse e si compie quando tutte le di esse fanno e rifiuta quando uno di loro rifiuta. Si potrebbe voler aggiungere un gestore .catch nel caso in cui una delle query non riesca o utilizzare .done per indicare la fine di una catena. Altre librerie di promesse come Bluebird raccoglieranno errori anche senza .done o aggiungendo un gestore esplicito, purtroppo Q non lo fa.

+4

FYI:. 'FindOne() exec()' restituisce una promessa. – WiredPrairie

+2

@WiredPrairie in questo caso - OP deve assolutamente usare 'findOne (..). Exec' invece di preoccuparsi di nfcall o prometterlo manualmente. OP - nota anche questo significa che non hai bisogno di tutte le cose '.if (err)', le promesse si prendono cura di te per te. –

4

Si potrebbe anche usare q (NPM installare q)

var q = require('q') 
, aPromise = mongooseModelA.find({_id: aId}).exec() 
, bPromise = mongooseModelB.find({_id: bId}).exec(); 

q.all([aPromise, bPromise]).then(function(bothA_and_B) { 
    console.log(bothA_and_B); 
}); 
Problemi correlati