已解决,请查看答案。
我有一个使用请求获取的网址列表,由于某种原因,当我尝试一次获取 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/