Nodejs中async的eachLimit方法内使用superagent的疑惑

Nodejs中async的eachLimit方法内使用superagent的疑惑

在抓网页遇到这样一个问题:

async.eachLimit(dataArr, 100,
    function(item, callback) {
        superagent
            .get('url')
            .query({ act: item })
            .end(function(err,res){
                if (err) {
                    return console.error("someErr: ", err);
                }
                var idata = JSON.parse(res.text);
                idata = idata.toString() + "\n";
                fs.appendFile('data.txt', idata, function (err) {
                  if (err) throw err;
                  console.log('The "data to append" was appended to file!');
                });
            });
    },
    function(err) {
        log('Get err: ' + err);
    });

每次只获取100个数据后,程序就结束了,没有继续下一批数据获取。不太明白什么原因,希望大侠指点!


4 回复

标题:Nodejs中async的eachLimit方法内使用superagent的疑惑

内容: 在使用Node.js处理异步任务时,async.eachLimit 方法可以有效地限制同时执行的任务数量,以避免对系统资源造成过大压力。然而,在实际应用中,可能会遇到一些问题,比如你提到的每次只获取100个数据后,程序就停止了,而不是继续下一批数据的获取。

首先,让我们来分析一下你的代码片段:

const async = require('async');
const superagent = require('superagent');
const fs = require('fs');

async.eachLimit(dataArr, 100, // 这里应该是限定的同时处理的最大任务数,例如5
    function(item, callback) {
        superagent
            .get('http://example.com') // 假设这是你要请求的URL
            .query({ act: item })
            .end(function(err, res){
                if (err) {
                    return callback(err); // 注意这里需要调用callback,将错误传递给eachLimit
                }
                var idata = JSON.parse(res.text);
                idata = idata.toString() + "\n";
                fs.appendFile('data.txt', idata, function (err) {
                  if (err) return callback(err); // 同样,这里也需要调用callback
                  console.log('The "data to append" was appended to file!');
                  callback(); // 正常情况下也应调用callback,表示当前任务已完成
                });
            });
    },
    function(err) {
        if (err) {
            log('Get err: ' + err);
        } else {
            console.log('All data processed successfully.');
        }
    }
);

解析与修正

  1. 参数问题:在 async.eachLimit 的第二个参数中,你需要指定的是最大并发任务数,而不是任务总数。例如,如果你想同时处理最多5个任务,应该这样写:

    async.eachLimit(dataArr, 5, ...
    
  2. 回调函数:在每个任务完成时(无论是成功还是失败),都需要调用 callback 函数。这告诉 async.eachLimit 当前任务已经结束,可以继续处理下一个任务。在你的代码中,superagent 请求结束后需要调用 callback,并且在文件写入完成后也需要调用 callback

  3. 错误处理:确保在出现错误时正确地调用 callback 并传入错误对象,这样 async.eachLimit 可以捕获到错误并终止后续任务的执行。

通过上述调整,你的代码应该能够正确地按预期工作,即在限定的最大并发任务数范围内逐个处理数据,并且不会在处理完一部分数据后提前终止。


没有调用callback函数,在end的时候调用一下callback即可

你提到的问题可能是由于 superagent 请求是异步的,而 async.eachLimit 并没有正确地等待这些异步操作完成。你需要确保每个 superagent 请求完成之后才调用回调函数 callback。你可以通过使用 async.eachLimit 的错误处理机制来解决这个问题。

示例代码

const async = require('async');
const superagent = require('superagent');
const fs = require('fs');

const dataArr = [/* 你的数据数组 */];

async.eachLimit(dataArr, 100, 
    function(item, callback) {
        superagent
            .get('http://example.com') // 替换为实际URL
            .query({ act: item })
            .end(function(err, res) {
                if (err) {
                    return callback(err); // 使用callback来传递错误
                }
                try {
                    const idata = JSON.parse(res.text);
                    idata = idata.toString() + "\n";
                    fs.appendFile('data.txt', idata, function (err) {
                        if (err) {
                            return callback(err); // 使用callback来传递错误
                        }
                        console.log('The "data to append" was appended to file!');
                        callback(); // 数据写入成功,继续下一个item
                    });
                } catch (e) {
                    callback(e); // 解析JSON失败,传递错误
                }
            });
    }, 
    function(err) {
        if (err) {
            return console.error("Some error occurred: ", err);
        }
        console.log('All data has been processed successfully.');
    }
);

关键点解释

  1. 回调函数callbacksuperagent 请求完成后被调用,以通知 async.eachLimit 下一个数据项可以开始处理了。
  2. 错误处理:在 superagent 请求或文件写入过程中,如果发生错误,则需要调用 callback(err) 来传递错误。这样 async.eachLimit 就能知道当前任务已经失败,并停止后续任务。
  3. 异步操作顺序:确保每个异步操作(如 superagent 请求和文件写入)完成后,才调用 callback,从而允许 async.eachLimit 正确管理并发度。

通过这种方式,async.eachLimit 可以正确地等待每个异步任务完成,从而保证所有数据项都被处理。

回到顶部