node.js中ForEach中的异步请求

node.js中ForEach中的异步请求,node.js,asynchronous,foreach,requestjs,Node.js,Asynchronous,Foreach,Requestjs,我不熟悉node.js(和request.js)。我希望从具有不同路径的特定url(在下面的示例中,等等)获取网站正文,并使用键/值映射(下面的siteData[path])将此数据记录到对象中 我的问题是: if语句(index==length)看起来不是确定异步请求是否完成的正确方法。如何正确检查请求是否已完成 当我执行上面的代码时,我得到一个错误(节点)警告:检测到可能的EventEmitter内存泄漏。添加了11个未管道侦听器。使用emitter.setMaxListeners()增加

我不熟悉node.js(和request.js)。我希望从具有不同路径的特定url(在下面的示例中,等等)获取网站正文,并使用键/值映射(下面的siteData[path])将此数据记录到对象中

我的问题是:

  • if语句(index==length)看起来不是确定异步请求是否完成的正确方法。如何正确检查请求是否已完成
  • 当我执行上面的代码时,我得到一个错误
    (节点)警告:检测到可能的EventEmitter内存泄漏。添加了11个未管道侦听器。使用emitter.setMaxListeners()增加限制。
    我尝试链接
    请求(url,函数(…){})但这不起作用

谢谢你的帮助

由于nodejs中
请求
方法的异步性质,您无法直接知道他们的响应并实时采取行动。您必须等待回调到达,然后只有您可以调用下一个
request
方法

在本例中,您正在调用
forEach
循环中的所有
request
方法,这意味着它们将在不等待之前的响应的情况下被逐个调用

为此,我建议使用奇妙的
async
库,如下所示-

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

async.whilst(
  function () { return count < pathLength; },
  function (callback) {
    // do your request call here 
    var path = paths[pathLength];
    var url="http://www.example.com/"+path;
  request(url, function(error, response, html){
    if(!error){
        siteData[path] = response.body;
         // call another request method
        count++;
        callback();
    }
   });
 },
 function (err) {
  // all the request calls are finished or an error occurred
  // manipulate data here 
  someFunction(siteData);
 }
);
var async=require('aysnc');
var request=require('request'),
路径=['path1'、'path2'、'path3'],
siteData={},
pathLength=path.length,
路径索引=0,
计数=0;
异步的(
函数(){return count

希望这有帮助。

由于nodejs中的
请求
方法的异步性质,您无法直接知道他们的响应并实时采取行动。您必须等待回调到达,然后只有您可以调用下一个
request
方法

在本例中,您正在调用
forEach
循环中的所有
request
方法,这意味着它们将在不等待之前的响应的情况下被逐个调用

为此,我建议使用奇妙的
async
库,如下所示-

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

async.whilst(
  function () { return count < pathLength; },
  function (callback) {
    // do your request call here 
    var path = paths[pathLength];
    var url="http://www.example.com/"+path;
  request(url, function(error, response, html){
    if(!error){
        siteData[path] = response.body;
         // call another request method
        count++;
        callback();
    }
   });
 },
 function (err) {
  // all the request calls are finished or an error occurred
  // manipulate data here 
  someFunction(siteData);
 }
);
var async=require('aysnc');
var request=require('request'),
路径=['path1'、'path2'、'path3'],
siteData={},
pathLength=path.length,
路径索引=0,
计数=0;
异步的(
函数(){return count

希望这能有所帮助。

看起来承诺是完成工作的正确工具。我们将创建一个新的
Promise
对象,而不是回调,该对象将在作业完成时解析。我们可以用
说“完成后,再做一些事情”。然后
操作符:

var rp = require('request-promise');

rp('http://www.google.com')
  .then((htmlString) => {
    // Process html... 
  });

(如果出现任何问题,承诺将拒绝并直接转到
.catch

我们有很多异步任务要做,所以只有一个承诺是行不通的。一种选择是将它们串联在一起,如下所示:

rp('http://www.google.com')
  .then((htmlString) => rp('http://someOtherUrl.com'))
  .then((otherHtmlString) => {
    // and so forth...
但这失去了异步的一些优点——我们可以并行完成所有这些任务

那看起来真难看。有一种更好的方法可以实现这一切-(您使用的是箭头函数,所以我假设native
Promise
也适用于您)。它接受一个承诺数组并返回一个承诺,该承诺在该数组的所有承诺都已执行完毕时解析。(如果其中任何一个错误,它将立即拒绝)。
。然后
函数将获得一个数组,表示每个承诺解析到的值

var myRequests = [];
myRequests.push(rp('http://www.google.com'));
myRequests.push(rp('http://someOtherUrl.com'));
Promise.all(myRequests)
  .then((arrayOfHtml) => {
    // arrayOfHtml[0] is the results from google,
    // arrayOfHtml[1] is the results from someOtherUrl
    // ...etc
    arrayOfHtml.forEach(processStuff);
  })
  .catch(/* handle error */);
尽管如此,我们仍然必须手动调用
。为每个我们想要点击的链接推送
。那不行!让我们使用一个巧妙的技巧在数组上迭代,依次处理每个值并返回一个由新值组成的新数组:

var arrayOfPromises=path.map((path)=>rp(`http://www.example.com/${path}`);
承诺。全部(协议书)
.then((arrayOfHtml)=>arrayOfHtml.forEach(processStuff))
.catch(函数(err){console.log('agh!');});

更干净、更容易处理错误。

看起来承诺是完成这项工作的正确工具。我们将创建一个新的
Promise
对象,而不是回调,该对象将在作业完成时解析。我们可以用
说“完成后,再做一些事情”。然后
操作符:

var rp = require('request-promise');

rp('http://www.google.com')
  .then((htmlString) => {
    // Process html... 
  });

(如果出现任何问题,承诺将拒绝并直接转到
.catch

我们有很多异步任务要做,所以只有一个承诺是行不通的。一种选择是将它们串联在一起,如下所示:

rp('http://www.google.com')
  .then((htmlString) => rp('http://someOtherUrl.com'))
  .then((otherHtmlString) => {
    // and so forth...
但这失去了异步的一些优点——我们可以并行完成所有这些任务

那看起来真难看。有一种更好的方法可以实现这一切-(您使用的是箭头函数,所以我假设native
Promise
也适用于您)。它接受一个承诺数组并返回一个承诺,该承诺在该数组的所有承诺都已执行完毕时解析。(如果其中任何一个错误,它将立即拒绝)。Th
'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);
};
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