具有异步队列和瀑布的猫鼬

Unm*_*eow 2 asynchronous mongoose mongodb node.js

我的目标是通过 Mongoose 导入大量数据。作为新手,我无法通过异步使用各种机制正确设置流量控制。很高兴有人可以指出适当的解决方案。谢谢。

var async = require('async'),
    mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/test');
var Cat = mongoose.model('Cat', { name: String });

// Imagine this is a huge array with a million items.
var content = ['aaa', 'bbb', 'ccc'];
var queries = [];
content.forEach(function(name) {
  queries.push(function(cb) {
    var obj = new Cat({ name: name });
    obj.save(function(err) {
      console.log("SAVED: " + name);
      console.log(err);
    });
    return true;
  });
});

// FAILED: async.parallel adds all content to db, 
// but it would exhaust the resource with too many parallel tasks.
async.parallel(queries, function(err, result) {
  if (err)
    return console.log(err);
  console.log(result);
});

// FAILED: save the first item but not the rest
async.waterfall(queries, function(err, result) {
  if (err)
    return console.log(err);
  console.log(result);
});

// FAILED: same as async.waterfall, async.queue saves the first item only
var q = async.queue(function(name, cb) {
  var obj = new Cat({ name: name });
  obj.save(function(err) {
    console.log("SAVED: " + name);
    console.log(err);
  });
})
q.push(content, function (err) {
  console.log('finished processing queue');
});
Run Code Online (Sandbox Code Playgroud)

rob*_*lep 5

我认为eachLimiteachSeries最适合您的情况:

var content = ['aaa', 'bbb', 'ccc'];
async.eachLimit(content, 10, function(name, done) {
  var obj = new Cat({ name : name });
  obj.save(done);
  // if you want to print some status info, use this instead:
  //
  // obj.save(function(err) {
  //   console.log("SAVED: " + name);
  //   console.log(err);
  //   done(err);
  // });
  //
}, function(err) {
  // handle any errors;
});
Run Code Online (Sandbox Code Playgroud)

使用eachLimit,您可以“并行”运行 X 个查询(在上面的示例中为 10 个)以加快速度而不会耗尽资源。eachSeries将在继续下一个之前等待上一个保存,因此一次有效地保存一个对象。

请注意,使用each*,您将不会获得包含(已保存)对象的列表(这是一种即发即忘的机制,您对结果不感兴趣,禁止出现任何错误)。如果您最终确实想要保存对象的列表,则可以使用等效的map*函数:mapLimitmapSeries