关于async包的eachSeries串行执行一组异步任务的问题
发布于 9 年前 作者 ipengzhou 8786 次浏览 最后一次编辑是 8 年前 来自 问答

最近在写一个爬虫程序,遇到一个问题,在使用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);
};

我怀疑是数据库的连接池代码问题,不太请求,问题也不够清晰,有大神凑合帮忙看一下吧

3 回复

问题找到了,原因是我使用的数据库连接池执行任务的,但是在连接数据库的默认配置最大连接数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();
    });
  });
};
回到顶部