Node.js用于循环异步请求

时间:2015-08-31 11:01:53

标签: node.js asynchronous

我有一个请求循环(和回调中的另一个请求)。

我有内存使用问题(当我同时经历大量请求时)

这是示例代码:

var request = require('request');

for(var j=1;j<=10;j++){

            request({
              method: 'GET',
              url: 'https://api.domain.com/items/?page='+j+'&limit=1000',
              headers: {
                'Content-Type': 'application/json'
              }}, function (error, response, body) {

              var data = JSON.parse(body)


              for(var i=0;i<data.length;i++){

                    request({
                      method: 'GET',
                      url: 'https://api.domain.com/itemDetail/'+data[i].id,
                      headers: {
                        'Content-Type': 'application/json',
                      }}, function (error, response, body) {


                        var itemDetails = JSON.parse(body);

                        // save items to mongodb          

                        }

              }
    });


}

解决方案向我建议使用async模块。

阅读文档后,我发现eachlimit符合我的需要。

我有它的问题我可以使用每个限制为第二个循环但是对于第一个循环我不知道如何使用它(因为第一个循环不是数组)。

到目前为止,我得到的代码,它不起作用:

var request = require('request');
var mongodb = require('mongodb');
var async = require('async');

var MongoClient = mongodb.MongoClient;

var url = 'mongodb://localhost:27017/subtitle';

for(var j=1;j<=10;j++){

        request({
              method: 'GET',
              url: 'https://api-v2.domain.com/news/popular?page='+j+'&limit=1000',
              headers: {
                'Content-Type': 'application/json',
                'api-version': '2',
                'api-key': 'my-api-key'
              }}, function (error, response, body) {

                    try {
                        var data = JSON.parse(body);
                        } catch (e) {
                          // An error has occured, handle it, by e.g. logging it
                              console.log(e);
                        }

                            async.each(data, function(item, callback) {

                                    request({
                                      method: 'GET',
                                      url: 'https://api-v2.domain.com/news/'+item.id,
                                      headers: {
                                            'Content-Type': 'application/json',
                                            'api-version': '2',
                                            'api-key': 'my-api-key'
                                          }}, function (error, response, body) {
                                            // sava item in mongodb
                                      })



                                callback();

                            }, function(err){

                                if( err ) {
                                  console.log('A item failed to process');
                                } else {
                                  console.log('All items have been saved successfully');
                                }
                            });


              })


}

1 个答案:

答案 0 :(得分:3)

你可以通过多种方式实现这一目标,其中一种方式可以使用。使用您的代码,它看起来像这样(删除了错误处理和请求选项以提高可读性):

var requestCount = 0;

async.whilst(
    function () { 
        return requestCount < 10; 
    },
    function (firstCallback) {

        request({url: "https://api-v2.domain.com/news/popular?page=" + requestCount + "&limit=1000"}, function (err1, res1, body1) {

            var data = JSON.parse(body1);

            async.each(
                data, 
                function(item, secondCallback) {

                    request({url: "https://api-v2.domain.com/news/" + item.id}, function (err2, res2, body2) {
                        // sava item in mongodb
                        secondCallback();
                    }); 
                },
                function(err){
                    requestCount++;
                    firstCallback();
                }
            );
        });
    },
    function (err) {
        //all requests done
    }
);

一旦你开始嵌套这么多的回调,你应该重构它并将第二个循环放在它自己的函数中。例如:

var requestCount = 0;

async.whilst(
    function () { 
        return requestCount < 10; 
    },
    function (callback) {

        request({url: "https://api-v2.domain.com/news/popular?page=" + requestCount + "&limit=1000"}, function (err, res, body) {

            var items = JSON.parse(data);

            getNews(items, function(newsErr){
                requestCount++;
                callback(newsErr);
            });
        });
    },
    function (err) {
        //all requests done
    }
);


//----------------------------------------------------
function getNews(items, callback){

    async.each(items, function(item, itemCallback) {

        request({url: "https://api-v2.domain.com/news/" + item.id}, function (err2, res2, body2) {
            // sava item in mongodb
            itemCallback();
        }); 
    }, callback);
}

还要确保在请求的回调中调用异步回调(您在代码中没有这样做)。