Adrien Pecher
Adrien Pecher

Reputation: 357

Multiple errors when trying to save to DB using mongoose and async

i am trying to save something to a database using mongoose. The thing is i need to make sure the save was completed before i move on in the program and close the connection. Knowing that save is async in mongoose i tried using this code:

saveFunction = function(song){
song.save(function(err, userObj){
    if(err){
        console.log('Error' + err);
    } else{
        console.log('saved successfully:', userObj);
    }

});
};

database.prototype.add= function(newSong){
mongoose.connect(url);

var song = new songModel({id : newSong.getId(),
    title : newSong.getTitle(),
    artist : newSong.getArtist,
    genre : newSong.getGenre(),
    rating : newSong.getRating(),
    link : newSong.getLink()});


console.log("before async");
async.parallel([function (callback){
    saveFunction(song);
    callback();
}],function(){
    mongoose.connection.close();
    console.log('closed connection');
});
console.log("after async");
nextFreeId++;
};

^songModel is defined globally.

I tried lots of different methods and changed lots of thing but i always get and error of somekind. With this code i get a process.nexttick(function() throw err ) error. I just can't get it to work. Can someone tell me whats wrong or provide me with working code?

I think optimally the console should look like this:

before async
saved successfully
closed connection
after async

Thanks!

EDIT: Open to other alternatives to async aswell. I just want to get this code to work any way possible. I just need to save/find something/remove something and it needs to wait with the rest of the execution of the program until the save/find/removal is done. I'm getting pretty desperate, lost nearly a day on this problem alone on a tight shedule :(

Upvotes: 2

Views: 210

Answers (1)

Alex Logan
Alex Logan

Reputation: 1241

You need to return a callback from your save function.

saveFunction = function(song,callback){
    song.save(function(err, userObj){
        if(err){
            console.log('Error' + err);
            return callback(true,err)
        } else{
            console.log('saved successfully:', userObj);
            return callback(null);
        }
    });
};

Edit

From your comment, the behavior you are expecting will never occur. You are expecting

console.log("before async");

async.parallel -> do your bits 
console.log('closed connection');

console.log("after async");

However this will never happen because async.parallel is an asynchronous call, which means that the execution does not wait for it to finish before moving onto the next command. The behavior you are seeing is

console.log("before async");

async.parallel -> starts

console.log("after async");

async.parallel -> console.log('closed connection');

Node is doing the first log, starting the async.parallel, then console.logging "after async". Then when async.parallel gets to its callback function, it prints "closed connection", so it appears after "after async" because it was executed after.

Any logic you want to perform that relies on the result of async.parallel must happen in the callback function. Furthermore, async.parallel is used when you want to run 2 or more functions asynchronously, then execute a callback once they are all finished. Your solution does not require async.parallel. You can replace that with:

saveFunction(song,function(err){
    if(err){
        //failed to save song
    }
    mongoose.connection.close(); //you do not need to do this anyway
    console.log('closed connection');
    nextFreeId++;
    //anything else you need to do here
});

Upvotes: 2

Related Questions