2012-08-11 14 views
7

Come gestisco il salvataggio dei lotti in Mongoose? Ho visto che non può essere ancora possibile:La Mongoose JS promette? O come gestire il salvataggio dei lotti

Theres qualche cenno su come utilizzare qualche libreria di controllo di flusso come q, ma ho anche notato ci promises in mangusta, può essere utilizzato? Posso fare come in jQuery differite/promesse

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

risposta

3

Provare la funzione parallel del modulo 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

di salvare più documenti Mongoose in parallelo, si può fare qualcosa di semplice come questo (supponendo che si dispone di una matrice denominata docs di documenti per risparmiare):

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

Un raffinato esempio su come utilizzare async parallel sarebbe:

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

Dal momento che la convenzione è lo stesso in Mongoose come in asincrone (err, callback) non è necessario di metterli in le tue richiamate, aggiungi le tue chiamate di salvataggio in un array e riceverai una richiamata quando tutto sarà finito.

+1

Oppure a batch-save an array: async.map (oggetti, funzione (oggetto, successivo) {oggetto.salvataggio (successivo)}, callback); –

+0

Grazie. Penso che l'approccio alla mappa sia migliore. Ma entrambi stanno bene. –

9

Sì, lo puoi fare con le promesse. Codice Se si sta utilizzando la libreria Q promessa, si potrebbe ri-scrittura di @ matz3 come:

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

Partiamo tutte le operazioni una alla volta nel ciclo, ma non aspettare per nessuno di loro di completo, quindi corrono in parallelo. Aggiungiamo una promessa (che si comporta come un segnaposto per il risultato) a un array. Aspettiamo quindi tutte le promesse nella serie di promesse da completare.

La maggior parte buona Promises/A+ librerie compatibili hanno un qualche equivalente a Q.all

+0

Novità di questo potrebbe essere sbagliato. Ma il tuo save() lì quando costruisci l'array, non dovresti escludere il() così da non valutare durante la costruzione dell'array? – Slappy

+1

No, sto iniziando le operazioni nell'array, quindi ho bisogno di includere '()'. Ciò restituisce quindi un oggetto 'promise' che inserisco nell'array. È parallelo perché ottengo solo una promessa, non il risultato finale effettivo. Alla fine, attendo che queste promesse si risolvano. – ForbesLindesay

+1

Se dovessi omettere il '()' otterrei una serie di funzioni, e non c'è una cosa universalmente riconosciuta da fare con una serie di funzioni. Ad esempio, potrei volere che eseguissero uno alla volta piuttosto che in parallelo, oppure potrebbero richiedere una richiamata piuttosto che restituire una promessa. Esiste tuttavia un modo riconosciuto di attendere che una serie di promesse siano soddisfatte. – ForbesLindesay

-1

Che dire async.queue.
Un semplice esempio:

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

Se avete bisogno di una richiamata dopo la coda viene svuotata:

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

Perché un downvote? – mathieug

-1

@ForbesLindesay Perché il caricamento di una libreria esterna quando si può usare l'esecuzione mangusta di promesse e creare il proprio Tutti ?

Creare un modulo che migliori la promessa della mangusta con tutti.

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; 

Quindi utilizzare con 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

Bene, sembra più semplice usare semplicemente mpromise che è usato all'interno di mangusta: 'var Promise = require ('mpromise');' quindi usa 'Promise.all (...)'. –

4

mangusta ora consente di scegliere che promettono attuazione.

Qui sto usando il nodo.Sistema js predefinito Promise (ES6) cotto in 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(); 
}); 

nodo --version v4.1.1

[email protected]

1

Dal mongoose ora supporta le promesse si può utilizzare Promise.all().then(), quindi ritornerà quando tutte le promesse saranno risolte.

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

In realtà, se si sta sempre chiamando il metodo save() è possibile utilizzare il Array.map() qui:

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

Eeee anche utilizzare ES6 sintassi per destrutturare la matrice risultante:

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