Reputation: 1089
In the following code, I try to populate my dev DB with some test data. I would like to first delete all documents and then add new test ones:
var mongoose = require('mongoose')
, Plan = mongoose.model('Plan')
, Async = require('async')
Async.series([
function(callback){
// delete all records
Plan.find(function(err,docs){
for (d in docs)
Plan.remove(d, function(err) {
if (err) console.log("error removing records " + err)
});
});
callback();
},
function(callback){
var planArray = [
{title: 'Plan A', body: 'Restaurant Financial Plan'},
{title: 'Plan B', body: 'Coffeeshop Financial Plan'},
{title: 'Plan C', body: 'bar Financial Plan'}
]
var arrayLength = planArray.length;
for (var i = 0; i < arrayLength; i++) {
var p = new Plan(planArray[i])
p.save(function(err, saved){
if (err)
{console.log("error creating fixture " + err)}
else {
console.log(saved)
}
})
}
callback();
}
])
The interesting (strange) behaviour is this: - the code runs and removes all documents but does not add the new test ones. - no errors on the console, the console.log(saved) prints each new document to the console successfully. - if I remove the first Async function (delete all records) - then the new docs are saved into the DB.
a mongoose quirk or my misunderstanding of async flow..?
Upvotes: 1
Views: 400
Reputation: 151092
There were a few problems. Firstly you have a for
loop that is firing of async removes, but these were likely not completing before your first callback was called. Better to use Async.each
instead.
Also there seems to be some function naming collision happening. So for a complete example of this see the following:
var mongoose = require('mongoose'),
Async = require('async'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var planSchema = new Schema({
title: String,
body: String
});
var Plan = mongoose.model('Plan',planSchema);
Async.series([
function(call1) {
Plan.find(function(err,docs) {
if (err)
throw err;
if ( docs.length > 0 ) {
Async.each( docs, function(d, call2) {
Plan.remove(d, function(err) {
if (err)
throw err;
console.log( "deleting: " + d );
call2();
});
});
}
});
call1();
},
function(call3) {
var planArray = [
{ title: 'Plan A', body: 'Plan A' },
{ title: 'Plan B', body: 'Plan B' }
];
var arrayLength = planArray.length;
for ( var i = 0; i < arrayLength; i++ ) {
var p = new Plan(planArray[i]);
p.save(function(err,saved) {
if (err)
throw err;
console.log( "saving: " + saved );
});
}
call3();
}
]);
Upvotes: 2
Reputation: 2917
Second function starts execution after you call callback(), i. e. before find and remove calls. You have to wait until find and remove are done and the call callback(). Have a look at queue method from async: https://github.com/caolan/async#queue
Upvotes: 0
Reputation: 2080
My guess is the latter--a misunderstanding of async flow. Your callback on the first function is invoked before you finish finding and removing documents. So while you're still finding and removing them, you are already adding some more in the second function--but these will be found and removed by the first.
You need to call the first callback only after deleting all documents. Try putting an async.each
within your Plan.find
callback:
Async.series([
function(callback){
// delete all records
Plan.find(function(err, docs){
Async.each(
docs, // your array
function removeDoc(d, cb) { // iterator function
Plan.remove(d, function (err) {
if (err) console.log("error removing records " + err);
return cb();
});
},
callback // executed after the iterator is done
);
},
...
Incidentally, I believe Plan.remove({}, function(err){...})
deletes all documents--no need to iterate over each document unless of course you're doing something else.
Upvotes: 1