2012-08-11 9 views
7

Jak zarządzać oszczędzaniem partii w Mongoose? Widziałem, że nie może być jeszcze możliwe:Mongoose JS obiecuje? Lub jak zarządzać zbiorowym zapisem

Tam jakieś wzmianki o użyciu niektóre biblioteki sterowania przepływem jak q, ale również zauważyć tam promises w mangusta, może być używany? Mogę zrobić tak jak w jQuery odroczony/Promises

$.when(obj1.save(), obj2.save(), obj3.save()).then -> 
    # do something? 

Odpowiedz

3

Wypróbuj funkcję parallel modułu async.

var functions = []; 

for (var i=0; i < docs.length; i++) { 
    functions.push((function(doc) { 
     return function(callback) { 
      doc.save(callback); 
     }; 
    })(docs[i])); 
} 

async.parallel(functions, function(err, results) { 
    console.log(err); 
    console.log(results); 
}); 
2

Aby zapisać wiele docs Mongoose równolegle, można zrobić coś prostego, jak to (zakładając, że masz tablicę o nazwie docs dokumentów, aby zapisać):

var count = docs.length; 
docs.forEach(function(doc) { 
    doc.save(function(err, result) { 
     if (--count === 0) { 
      // All done; call containing function's callback 
      return callback(); 
     } 
    }); 
}); 
1

Wyrafinowany przykład jak używać async parallel byłoby:

async.parallel([obj1.save, obj2.save, obj3.save], callback); 

ponieważ konwencja jest taka sama jak w Mongoose w async (eee, callback) nie trzeba zawinąć je w własne wywołania zwrotne, po prostu dodaj połączenia zapisywania w tablicy, a otrzymasz wywołanie zwrotne, gdy wszystko zostanie zakończone.

+1

Lub batch-save array: async.map (obiekty, funkcja (obiekt, następny) {object.save (następny)}, wywołanie zwrotne); –

+0

Dzięki. Myślę, że podejście mapowe jest lepsze. Ale oba są w porządku. –

9

Tak, możesz to zrobić z obietnicami. Kod jeśli były przy użyciu biblioteki Q obietnica, można ponownie napisać @ matz3 niczym:

var tasks = []; 

for (var i=0; i < docs.length; i++) { 
    tasks.push(docs[i].save()); 
} 

Q.all(tasks) 
    .then(function(results) { 
    console.log(results); 
    }, function (err) { 
    console.log(err); 
    }); 

Zaczynamy wszystkie operacje jedną naraz w pętli, ale nie czekaj na każdy z nich kompletny, więc działają równolegle. Do tablicy dodajemy obietnicę (która działa jak element zastępczy dla wyniku). Następnie czekamy na wszystkie obietnice w szeregu obietnic do wypełnienia.

Większość dobry Promises/A+ kompatybilne biblioteki mają jakiś odpowiednik Q.all

+0

Nowość w tym może być nie tak. Ale twoje save() tam podczas budowania tablicy, nie należy wykluczać(), więc nie ocenia podczas budowania tablicy? – Slappy

+1

Nie, zaczynam operacje w tablicy, więc muszę dołączyć '()'. Następnie zwraca obiekt "obietnica", który umieściłem w tablicy. Jest to równoległe, ponieważ otrzymuję tylko obietnicę, a nie faktyczny wynik końcowy. Na koniec czekam, aż te obietnice rozwiążą. – ForbesLindesay

+1

Gdybym pominął '()', dostałbym całą gamę funkcji i nie ma powszechnie rozpoznawanej rzeczy z szeregiem funkcji. Na przykład, mogę chcieć, aby wykonywali je pojedynczo, a nie równolegle, lub mogą odbierać połączenia zwrotne zamiast zwracać obietnicę. Istnieje jednak jeden uznany sposób oczekiwania na wypełnienie szeregu obietnic. – ForbesLindesay

-1

Co o async.queue.
Prosty przykład:

var queue = async.queue(function(obj, callback) { 
    return obj.save(callback); 
}); 

for (var i in objs) { 
    var obj = objs[i]; 
    // Some changes on object obj 
    queue.push(obj); 
} 

Jeśli potrzebujesz zwrotnego po kolejka jest opróżniany:

var emptyQueue = true; 
var queue = async.queue(function(obj, callback) { 
    return obj.save(callback); 
}); 
queue.drain = function() { 
    // Every callbacks are finished 
    // bigCallback(); 
}; 

for (var i in objs) { 
    var obj = objs[i]; 
    // Some changes on object obj 
    queue.push(obj); 
    emptyQueue = false; 
} 
if (emptyQueue) { 
    // Call manually queue drain in case of the queue is empty 
    // and we need to call bigCallback() for example 
    return queue.drain(); 
} 
+0

Dlaczego przegrana? – mathieug

-1

@ForbesLindesay Dlaczego ładowania zewnętrznej biblioteki, kiedy można użyć realizację Mongoose obietnic i tworzyć własne Wszystko ?

Utwórz moduł, który zwiększy obietnicę mangusty ze wszystkimi.

var Promise = require("mongoose").Promise; 

Promise.all = function(promises) { 
    var mainPromise = new Promise(); 
    if (promises.lenght == 0) { 
    mainPromise.resolve(null, promises); 
    } 

    var pending = 0; 
    promises.forEach(function(p, i) { 
    pending++; 
    p.then(function(val) { 
     promises[i] = val; 
     if (--pending === 0) { 
     mainPromise.resolve(null, promises); 
     } 
    }, function(err) { 
     mainPromise.reject(err); 
    }); 
    }); 

    return mainPromise; 
} 

module.exports = Promise; 

następnie używać go z mangusta:

require('./promise') 

... 

var tasks = []; 

for (var i=0; i < docs.length; i++) { 
    tasks.push(docs[i].save()); 
} 

mongoose.Promise.all(tasks) 
    .then(function(results) { 
    console.log(results); 
    }, function (err) { 
    console.log(err); 
    }); 
+0

Cóż, łatwiej jest po prostu użyć mpromise, która jest używana wewnątrz mangusty: 'var Promise = require ('mpromise');' następnie użyj 'Promise.all (...)'. –

4

mangusta teraz pozwala na wybór Obiecaj realizację.

Tutaj używam węzła.Domyślnym systemem js Obietnica (ES6) pieczone w nodejs

var mongoose = require('mongoose'); 
    mongoose.Promise = global.Promise; // use system implementation 

Promise.all(obj1.save(), obj2.save(), obj3.save()) 
.then(function(resultSaves) { 

    console.log('parallel promise save result :'); 
    console.log(resultSaves); 
    mongoose.disconnect(); 

}).catch(function(err) { 

    console.log('ERROR on promise save :'); 
    console.log(err); 
    mongoose.disconnect(); 
}); 

węzłów version v4.1.1

[email protected]

1

Od mongoose obsługuje teraz obietnice można użyć Promise.all().then(), więc powróci, gdy wszystkie obietnice zostaną rozwiązane.

Promise.all([ 
    obj1.save(), 
    obj2.save(), 
    obj3.save() 
]) 
.then(console.log) 
.catch(console.error) 

W rzeczywistości, jeśli jesteś zawsze wywołaniem metody save() można użyć Array.map() tutaj:

Promise.all([ obj1, obj2, obj3 ].map(obj => obj.save()) 

Aaand używać również ES6 składnię destructure wynikowy tablicy:

Promise.all([ obj1, obj2, obj3 ].map(obj => obj.save()) 
.then(([ savedObj1, savedObj2, savedObj3 ]) => { 
    // do something with your saved objects... 
}) 
Powiązane problemy