1

私はnode.js(およびrequest.js)が初めてです。異なるパスを持つ特定の URL から Web サイトの本文を取得したいと思います (以下の例ではhttp://www.example.com/path1http://www.example.com/path2など)。 )、このデータをキーと値のマッピングを使用してオブジェクトに記録します(以下の siteData[path])。

var request = require('request'),
    paths = ['path1','path2','path3'],
    siteData = {},
    pathLength = paths.length,
    pathIndex = 0;

paths.forEach((path) => {
    var url="http://www.example.com/"+path;
    request(url, function(error, response, html){
        if(!error){
            siteData[path] = response.body;
            pathIndex++;
            if(pathIndex===pathLength){
                someFunction(siteData);
            }
        }
});

function someFunction(data){
    //manipulate data
}

私の質問は次のとおりです。

  • if ステートメント (index === length) は、非同期要求が終了したかどうかを判断する正しい方法のようには見えません。リクエストが終了したかどうかを正しく確認するにはどうすればよいですか?
  • 上記のコードを実行すると、(node) warning: possible EventEmitter memory leak detected. 11 unpipe listeners added. Use emitter.setMaxListeners() to increase limit.チェーンを試行しましrequest(url, function(...){}).setMaxListeners(100);たが、うまくいきませんでしたというエラーが表示されます。

ご協力いただきありがとうございます!

4

4 に答える 4

2

私の経験では、非同期で実行されて EventEmitter メモリ リークが発生するため、リクエスト モジュールを処理するときに forEach やその他の種類のループを使用することはできません。

これを解決する方法は、再帰関数を使用することです。以下のコードを参照できます。

var request = require('request'),
    paths = ['path1','path2','path3'],
    siteData = {};

function requestSiteData(paths) {
    if (paths.length) {
        var path = paths.shift();
        var url = "http://www.example.com/" + path;

        request(url, function(error, response, html) {
            if(!error) {
                siteData[path] = response.body;
            } //add else block if want to terminate when error occur

            //continue to process data even if error occur
            requestSiteData(paths); //call the same function
        });
    } else {
        someFunction(siteData); //all paths are requested
    }
}

function someFunction(data){
    //manipulate data
}

requestSiteData(paths); //start requesting data
于 2015-12-02T08:44:23.603 に答える
0

私は、この場合はプロミスがおそらく進むべき道であるという上記の解決策に同意します。ただし、コールバックを使用して同じことを達成することもできます。

lodash ライブラリは、完了した非同期呼び出しの数を追跡する便利な方法を提供します。

'use strict';

var _ = require('lodash');
var path = require('path');

var paths = ['a', 'b', 'c'];
var base = 'www.example.com';

var done = _.after(paths.length, completeAfterDone);

_.forEach(paths, function(part) {
    var url = path.join(base, part);
    asynchFunction(url, function() {
        done();
    });
});

function completeAfterDone() {
    console.log('Process Complete');
}

function asynchFunction(input, cb) {
    setTimeout(function() {
        console.log(input);
        cb();
    }, Math.random() * 5000);
};

このメソッドを使用すると、done 関数は完了したリクエストの数を追跡し、各 URL が読み込まれると最終的なコールバックを呼び出します。

于 2015-12-01T02:44:17.597 に答える