我正在使用async.js在集合上运行for循环。出于性能原因,我想将数据库连接传递给iterator方法,以便它不会在每次迭代器运行时都打开/关闭数据库连接。我正在将mongoose.js用于数据模型。

下面的代码获取mongo中的所有Artists,然后为每位艺术家添加一首歌曲。我的问题是,如何在addArtistSong中使用来自updateAllArtists的相同数据库连接?

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


我可以以某种方式扩展迭代器签名,例如addArtistSong(artist,db,cb)吗?那我该如何通过forEach调用呢?

最佳答案

一种选择是使数据库连接成为全局变量。但是,如果您不希望这样,可以始终使用闭包在函数之间创建共享变量:

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


另一种选择是将其作为参数传递给addArtistSong。由于async.forEach期望迭代器函数仅接受2个参数,因此我们可以使用匿名函数包装器将3个参数传递给addArtistSong

function addArtistSong(db,artist,callback) {
    db.model(); //...
}


并在async.forEach中调用它:

async.forEach(
  artists,
  function(x,cb){addArtistSong(db,x,cb)},
  function(err) {}
);

10-06 01:13