Node.js 异步映射限制和内存

标签 node.js asynchronous

已解决,请查看答案。

我有一个使用请求获取的网址列表,由于某种原因,当我尝试一次获取 2000 个或更多网址时,我无法将超过 1720 条记录保存到我的数据库中。

如果我尝试 1000 到 2000 和 2000 到 3000,我总共会得到 3000 个结果。但是当我尝试 1000 到 3000 或 4000 到 6000 时,我的脚本在获取第 1720 个结果后停止。

这可能是什么原因?

我使用mapLimit来限制并发连接。

app.get('/asynctest', function(req, res) {
  var people = [];
  for (var a = 1000; a < 3000; a++) {
    people.push("http://www.example.com/" + a + "/person.html");
  }

  async.mapLimit(people, 20, function(url, callback) {
    // iterator function
    var options2 = {
      url: url,
      headers: {
        'User-Agent': req.headers['user-agent'],
        'Content-Type': 'application/json; charset=utf-8'
      }
    };

    request(options2, function(error, response, body) {
      if (!error && response.statusCode == 200) {
        async.series([
          // add this person into database
          function(callback) {
            var $ = cheerio.load(body);
            var name = entities.decodeHTML($('span[itemprop="name"]').text());
            new person({
              name: name,
              url: url
            }).save();
            callback();
          },

          function(callback) {
            async.waterfall([

              function(callback) {
                var $ = cheerio.load(body);
                var jobs = $('span[itemprop="jobtitle"]').length;
                if (jobs == 0) {
                  console.log("no job");
                  var jobsArr = 0;
                } else {
                  var jobsArr = [];
                  for (var aa = 0; aa < jobs; aa++) {
                    jobsArr.push(entities.decodeHTML($('span[itemprop="jobtitle"]').eq(aa).text()));
                  }
                }

                callback(null, jobsArr);
              },

              function(jobsArr, callback) {
                if (jobsArr == 0) {
                  console.log("this person has no jobs");
                } else {

                  async.map(jobsArr, function(jobs, callback) {
                    personRole.where('job_name', jobs).fetch({
                      require: true
                    }).then(function(data1) {
                      data1 = data1.toJSON();
                      person.where('url', url).fetch().then(function(data2) {
                        data2 = data2.toJSON();
                        new personPersonRole({
                          person_id: data2.id,
                          personrole_id: data1.id
                        }).save();
                      });
                    }).catch(function(err) {
                      new personRole({
                        job_name: jobs
                      }).save().then(function(data3) {
                        data3 = data3.toJSON();
                        person.where('url', url).fetch().then(function(data4) {
                          data4 = data4.toJSON();
                          new personPersonRole({
                            person_id: data4.id,
                            personrole_id: data3.id
                          }).save();
                        });
                      });
                    });
                  });
                }
                callback(null, "yes");
              }
            ], function(err, result) {
              if (err) {
                console.log(err);
              }
            });
            callback();
          }
        ], function(err, result) {
          if (err) {
            console.log("err3");
          }
        });
      } else {
        console.log("err4");
      }
    });
    callback();
  });
});

编辑#2

下面的代码也有问题,只添加了1747条记录,然后就停止了。如果我停止我的 Node 应用程序并再次启动,它也会停止在 1747。

var person = require('./models').person;

app.get('/asynctest', function(req, res) {
  var people = [];
 for (var a = 18000; a < 20000; a++) {
    people.push("random url");
  }

  async.mapLimit(people, 20, function(url, callback) {
    new person({
      name: "YES",
      url: url
    }).save();
    callback();
  });
});

db.js

var knex = require('knex')({
  client: 'mysql',
  connection: {
    host: '127.0.0.1',
    port: 8889,
    user: 'root',
    password: 'root',
    database: 'mydatabase',
    charset: 'utf8'
  },
  pool: {
    min: 0,
    max: 100
  }
});

var db = require('bookshelf')(knex);
module.exports = db;

models.js

var person = db.Model.extend({
  tableName: 'people'
});

module.exports = {
 person : person
};
<小时/>

编辑#3

好吧,我想我已经找到了解决方案。

18K-18.5K - no problem

18K-19K - no problem

18K-19.7K - no problem

18K-20K - RangeError: Maximum call stack size exceeded at new Object (native)

我刚刚将回调包装到包装器中,如下所示。

async.setImmediate(function () {
  callback();
});

  app.get('/async22', function(req, res) {
    var people = [];
    for (var a = 18000; a < 20000; a++) {
      people.push("yes");
  }

  async.mapLimit(people, 20, function(url, callback) {
    new person({
      name: "YES",
      url: url
    }).save();
      async.setImmediate(function () {
        callback();
      });
  });
});

最佳答案

它一直在我眼前,其实这个解决方案并不是唯一的,它已经包含了异步库的数据库。

https://github.com/caolan/async#common-pitfalls-stackoverflow

具体操作方法如下。

async.setImmediate(function () {
  callback();
});

示例

app.get('/async22', function(req, res) {
    var people = [];
    for (var a = 18000; a < 20000; a++) {
      people.push("yes");
  }

  async.mapLimit(people, 20, function(url, callback) {
    new person({
      name: "YES",
      url: url
    }).save();
      async.setImmediate(function () {
        callback();
      });
  });
});

关于Node.js 异步映射限制和内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34819003/

相关文章:

javascript - 如何为每个端点和 REST 方法设置不同的 Passport JS Bearer 策略?

javascript - 如何从 API 中删除 JWT 身份验证?

javascript - 浏览器渲染和 JavaScript 执行是否同时发生?

javascript - 同步迭代javascript对象

node.js - 如何在 stripe-node 中使用多个 Stripe key ?

javascript - Node.js : check if a property is absent from object

node.js - 如何计算elastic.js(elasticsearch)中具有相同值的字段?

c# - 为什么我在 `PageAsyncTask`注册的 `Page_Load`同步运行?

android - 如何从 Kotlin 异步闭包保存数据?

web-services - WP8 SDK import Service Reference with task-based operations not possible