Ich möchte einige Mongodb-Sammlungen löschen, aber das ist eine asynchrone Aufgabe. Der Code wird sein:
var mongoose = require('mongoose');
mongoose.connect('mongo://localhost/xxx');
var conn = mongoose.connection;
['aaa','bbb','ccc'].forEach(function(name){
conn.collection(name).drop(function(err) {
console.log('dropped');
});
});
console.log('all dropped');
Die Konsole zeigt Folgendes an:
all dropped
dropped
dropped
dropped
Was ist der einfachste Weg, um sicherzustellen, dass all dropped
wird gedruckt, nachdem alle Sammlungen gelöscht wurden? Jeder Drittanbieter kann zur Vereinfachung des Codes verwendet werden.
Wie ich sehe, verwenden Sie mongoose
, also sprechen Sie über serverseitiges JavaScript. In diesem Fall rate ich zu async module und benutze async.parallel(...)
. Sie werden dieses Modul als sehr hilfreich empfinden - es wurde entwickelt, um das Problem zu lösen, mit dem Sie zu kämpfen haben. Ihr Code könnte so aussehen
var async = require('async');
var calls = [];
['aaa','bbb','ccc'].forEach(function(name){
calls.Push(function(callback) {
conn.collection(name).drop(function(err) {
if (err)
return callback(err);
console.log('dropped');
callback(null, name);
});
}
)});
async.parallel(calls, function(err, result) {
/* this code will run after all calls finished the job or
when any of the calls passes an error */
if (err)
return console.log(err);
console.log(result);
});
Verwenden Sie Versprechen .
var mongoose = require('mongoose');
mongoose.connect('your MongoDB connection string');
var conn = mongoose.connection;
var promises = ['aaa', 'bbb', 'ccc'].map(function(name) {
return new Promise(function(resolve, reject) {
var collection = conn.collection(name);
collection.drop(function(err) {
if (err) { return reject(err); }
console.log('dropped ' + name);
resolve();
});
});
});
Promise.all(promises)
.then(function() { console.log('all dropped)'); })
.catch(console.error);
Dies löscht jede Sammlung, druckt nach jeder Sammlung "fallen gelassen" und druckt dann "alle fallen gelassen", wenn der Vorgang abgeschlossen ist. Wenn ein Fehler auftritt, wird er stderr
angezeigt.
Verwenden Sie Q Versprechen oder Bluebird Versprechen.
Mit [~ # ~] q [~ # ~] :
var Q = require('q');
var mongoose = require('mongoose');
mongoose.connect('your MongoDB connection string');
var conn = mongoose.connection;
var promises = ['aaa','bbb','ccc'].map(function(name){
var collection = conn.collection(name);
return Q.ninvoke(collection, 'drop')
.then(function() { console.log('dropped ' + name); });
});
Q.all(promises)
.then(function() { console.log('all dropped'); })
.fail(console.error);
Mit Bluebird :
var Promise = require('bluebird');
var mongoose = Promise.promisifyAll(require('mongoose'));
mongoose.connect('your MongoDB connection string');
var conn = mongoose.connection;
var promises = ['aaa', 'bbb', 'ccc'].map(function(name) {
return conn.collection(name).dropAsync().then(function() {
console.log('dropped ' + name);
});
});
Promise.all(promises)
.then(function() { console.log('all dropped'); })
.error(console.error);
Der Weg, dies zu tun, besteht darin, den Aufgaben einen Rückruf zu übergeben, der einen gemeinsam genutzten Zähler aktualisiert. Wenn der gemeinsame Zähler Null erreicht, wissen Sie, dass alle Aufgaben abgeschlossen sind, sodass Sie mit Ihrem normalen Ablauf fortfahren können.
var ntasks_left_to_go = 4;
var callback = function(){
ntasks_left_to_go -= 1;
if(ntasks_left_to_go <= 0){
console.log('All tasks have completed. Do your stuff');
}
}
task1(callback);
task2(callback);
task3(callback);
task4(callback);
Natürlich gibt es viele Möglichkeiten, um diese Art von Code allgemeiner oder wiederverwendbarer zu machen, und jede der viele asynchrone Programmierbibliotheken da draußen sollte mindestens eine Funktion haben, um diese Art von Dingen auszuführen.
Neben der @freakish-Antwort bietet async auch jede Methode an, die für Ihren Fall besonders geeignet zu sein scheint:
var async = require('async');
async.each(['aaa','bbb','ccc'], function(name, callback) {
conn.collection(name).drop( callback );
}, function(err) {
if( err ) { return console.log(err); }
console.log('all dropped');
});
IMHO, das macht den Code sowohl effizienter als auch lesbarer. Ich habe mir erlaubt, die Funktion console.log('dropped')
zu entfernen. Wenn Sie dies wünschen, verwenden Sie stattdessen diese Option:
var async = require('async');
async.each(['aaa','bbb','ccc'], function(name, callback) {
// if you really want the console.log( 'dropped' ),
// replace the 'callback' here with an anonymous function
conn.collection(name).drop( function(err) {
if( err ) { return callback(err); }
console.log('dropped');
callback()
});
}, function(err) {
if( err ) { return console.log(err); }
console.log('all dropped');
});
Ich mache das ohne externe Bibliotheken:
var yourArray = ['aaa','bbb','ccc'];
var counter = [];
yourArray.forEach(function(name){
conn.collection(name).drop(function(err) {
counter.Push(true);
console.log('dropped');
if(counter.length === yourArray.length){
console.log('all dropped');
}
});
});
Alle Antworten sind ziemlich alt. Seit Anfang 2013 unterstützt Mongoose nach und nach Versprechen für alle Abfragen. Dies ist also die empfohlene Methode, um mehrere asynchrone Aufrufe in der erforderlichen Reihenfolge zu strukturieren.
Wenn Sie Babel oder solche Transpiler verwenden und async/await verwenden, können Sie Folgendes tun:
function onDrop() {
console.log("dropped");
}
async function dropAll( collections ) {
const drops = collections.map(col => conn.collection(col).drop(onDrop) );
await drops;
console.log("all dropped");
}
Mit deferred
(ein weiteres Versprechen/eine verzögerte Implementierung) können Sie Folgendes tun:
// Setup 'pdrop', promise version of 'drop' method
var deferred = require('deferred');
mongoose.Collection.prototype.pdrop =
deferred.promisify(mongoose.Collection.prototype.drop);
// Drop collections:
deferred.map(['aaa','bbb','ccc'], function(name){
return conn.collection(name).pdrop()(function () {
console.log("dropped");
});
}).end(function () {
console.log("all dropped");
}, null);