I am using async.js to run a for loop over a collection. For performance reasons, I want to pass in a database connection into the iterator method, so that it's not opening/closing a db connection each time the iterator runs. I am using mongoose.js for my data models.
The code below gets all the Artists in mongo, and then adds a song for each. My question is, how can I use the same db connection from updateAllArtists in addArtistSong?
function updateAllArtists() {
var db = mongoose.createConnection('localhost/dbname');
var Artist = db.model('Artist', artistSchema);
Artist.find({}, function(err, artists) {
// for each artist, add a song
async.forEach(artists, addArtistSong, function(err) {
});
}
function addArtistSong(artist, cb) {
// THIS IS WHERE I NEED A DB CONNECTION
var Song = db.model('Song', songSchema);
}
Can I extend the iterator signature somehow, like addArtistSong(artist, db, cb)? Then how would I pass this in from the forEach call?
One option is to make the db connection a global variable. But if you don't want that you can always use a closure to create a shared variable between functions:
(function(){
// create db in this closure
var db = mongoose.createConnection('localhost/dbname');
function updateAllArtists() {
// now db is available here
var Artist = db.model('Artist', artistSchema);
Artist.find({}, function(err, artists) {
// for each artist, add a song
async.forEach(artists, addArtistSong, function(err) {});
});
}
function addArtistSong(artist, cb) {
// and also available here
var Song = db.model('Song', songSchema);
}
})()
Another option is to pass it as a parameter to addArtistSong
. Since async.forEach
expect the iterator function to accept only 2 parameters we can use an anonymous function wrapper to pass 3 parameters to addArtistSong
:
function addArtistSong(db,artist,callback) {
db.model(); //...
}
and calling it in async.forEach
:
async.forEach(
artists,
function(x,cb){addArtistSong(db,x,cb)},
function(err) {}
);