最近在写一个爬虫程序,遇到一个问题,在使用async包的eachSeries函数时碰到,该函数并没有完全执行完任务队列中的任务,代码如下:
- 连接mysql数据库,从连接池执行任务,代码如下:
"use strict";
const mysql = require('mysql');
const config = require('../config');
let pool = mysql.createPool(config.db);
/**
* 执行查询语句
* @param {String} sql
* @param {Array} params
* @param {Function} callback
*/
exports.query = (sql, params, callback) => {
pool.getConnection( (err, connection) => {
if (err) {
return callback(err, null);
}
connection.query(sql, params, callback);
});
};
- 通过async的eachSeries执行一组串行的异步任务代码如下:
exports.classList = (list, callback) => {
console.log(list.length); // => 16条数据
// 执行串行的异步任务【16个】,实际运行该代码后只执行了5次,eachSeries就退出了
async.eachSeries(list, function (item, next) {
db.query('select * from `class_list` where `id` =? limit 1', [item.id], (err, data) => {
if (err) {
return next(err);
}
if (Array.isArray(data) && data.length >= 1) {
// 数据已存在,更新
db.query('update `class_list` set `name`=?, `url`=? where `id`=?', [item.name, item.url, item.id], next);
} else {
// 数据不存在,添加
db.query('insert into `class_list`(`id`,`url`,`name`) values (?, ?, ?)', [item.id, item.url, item.name], next);
}
});
}, callback);
};
我怀疑是数据库的连接池代码问题,不太请求,问题也不够清晰,有大神凑合帮忙看一下吧
问题找到了,原因是我使用的数据库连接池执行任务的,但是在连接数据库的默认配置最大连接数connectionLimit为10 而我执行多个任务的时候,没有将数据库操作结束之后的连接释放回连接池,所以导致出问题了,修改connectionLimit为100或者更大就可以了。 其实还是没有解决根本的问题,应该在每一次执行数据库操作之后,将本次数据库连接释放到连接池中,因为我上面封装的连接池代码实现不了,我再想想该怎么解决这个问题吧
在你的query函数中,query完了后要release。 exports.query = (sql, params, callback) => { pool.getConnection( (err, connection) => { if (err) { return callback(err, null); } connection.query(sql, params, function(err, rows) { callback(err, rows); // do your callback firstly, connection.release(); // then release the connection }); }); };
我也没有用过mysql,可能有错,详见:https://github.com/felixge/node-mysql#pooling-connections
另外,使用promise会更方便,建议可以尝试别人已经包装好的mysql with promise:https://github.com/lukeb-uk/node-promise-mysql
@ron-liu 多谢哈,前两天天解决了,就是上面的方法,当时脑子糊涂,被回调给绕迷糊了,这么简单的给绕进去了
exports.query = (sql, params, callback) => {
pool.getConnection((err, connection) => {
if (err) {
return callback(err, null);
}
connection.query(sql, params, ()=> {
callback.apply(null, Array.from(arguments));
connection.release();
});
});
};