2014-04-01 14 views
11

Używanie mangusty do wysyłania wyników z db i Q dla obietnic, ale ciężko jest mi położyć głowę, po prostu zdobywając listę użytkowników, którzy są dostępni. Obecnie mam trochę coś takiego:Mongoose i obietnice: jak uzyskać tablicę wyników zapytania?

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) 

Jak bym go o konieczności zapytania zakończyć przed SomeOtherFunction bez robienia ton niechlujstwa wywołania zwrotne?

Odpowiedz

18

Inną propozycją byłoby użycie operatora MongoDB $in do przekazania tablicy do find i wydajnego uzyskania dużego zestawu wyników. Każdy będzie obiektem Mongoose.

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

Byłoby to o wiele bardziej wydajny niż czyni wiele żądań, po jednym dla każdej _id.

+1

Nigdy nie wiedziałem o tym '$ in', zdecydowanie spróbuję tego! –

+1

@delboud op, jeśli jest to odpowiedź, która zakończyła się rozwiązaniem problemu, powinieneś rozważyć zaakceptowanie jej nad moją, którą właśnie zaakceptowałeś. Szczerze mówiąc, podczas gdy moja odpowiedź daje dużo więcej podstaw teoretycznych i przydatnych informacji na temat obietnic IMO - jest to praktyczna odpowiedź dla osób stojących w obliczu tego problemu w Mongoose. Możesz odpowiedzieć na moją odpowiedź, jeśli uznasz to za przydatne, ale jestem za praktycznym rozwiązaniem :) –

+1

Właściwie zmagałam się z obietnicami, więc Twoja odpowiedziała na moje pytanie, ale dał mi wgląd w funkcję. Tak czy siak ze mną :) –

5

Odpowiedź na pytanie "jak kontynuować obietnice" jest prawie zawsze zgodna z .then. Jest to analogia obietnicy ; i kończy asynchroniczną instrukcję. Możesz w nim zwrócić obietnice, które rozwiną je przed kontynuowaniem.

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

Albo po prostu Q.all(promise).then(SomeOtherFunction)

będzie też trzeba findOne rzeczywiście powrócić obietnic. Możesz użyć Q.nfcall, która wywołuje funkcję węzła lub promisify it yourself.

To, co robi, to akceptacja szeregu obietnic i spełnienia, gdy wszystkie one spełniają i odrzucają, gdy jeden z nich odrzuci. Możesz dodać procedurę obsługi .catch, jeśli którekolwiek z zapytań zakończy się niepowodzeniem lub użyjesz .done w celu oznaczenia końca łańcucha. Inne obiecujące biblioteki, takie jak Bluebird, wychwycą dla ciebie błędy nawet bez .done lub dodania jawnego programu obsługi, niestety Q nie robi tego.

+4

FYI:. 'FindOne() exec()' zwraca obietnicę. – WiredPrairie

+2

@WiredPrairie w tym przypadku - OP powinien zdecydowanie używać 'findOne (..). Exec' zamiast zawracać sobie głowę nfcall lub promisifying it manualnie. OP - zauważ, że to oznacza, że ​​nie potrzebujesz całej rzeczy ".if (err)", obietnice dbają o nią. –

4

Można również użyć Q (npm zainstalować 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); 
}); 
Powiązane problemy