gpt4 book ai didi

node.js - Node.js 中 ForEach 内的异步请求

转载 作者:太空宇宙 更新时间:2023-11-03 22:40:36 24 4
gpt4 key购买 nike

我是node.js(和request.js)的新手。我想从具有不同路径的特定网址返回网站的正文(在下面的示例中 http://www.example.com/path1http://www.example.com/path2 等),并将这些数据记录在具有键/值映射的对象中(siteData [路径]如下)。

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 )警告:检测到可能的 EventEmitter 内存泄漏。添加了 11 个取消管道监听器。使用emitter.setMaxListeners() 来增加限制。 我尝试链接request(url, function(...){}).setMaxListeners(100); 但这不起作用。

感谢您的帮助!

最佳答案

看起来 Promise 是完成这里工作的正确工具。我们将创建一个新的 Promise 对象,而不是回调,该对象将在作业完成时解析。我们可以使用 .then 运算符说“一旦完成,再做一些事情”:

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

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

(如果出现任何问题, promise 将拒绝并直接进入.catch)

someFunctionThatErrors('Yikes!')
.then((data) => {
// won't be called
})
.catch((err) => {
// Will be called, we handle the error here
});

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

rp('http://www.google.com')
.then((htmlString) => rp('http://someOtherUrl.com'))
.then((otherHtmlString) => {
// and so forth...

但这失去了异步的一些优点 - 我们可以并行完成所有这些任务。

var myRequests = [];
myRequests.push(rp('http://www.google.com').then(processStuff).catch(handleErr));
myRequests.push(rp('http://someOtherUrl.com').then(processStuff).catch(handleErr));

...男孩,这看起来很丑吗?有一个更好的方法来解决这一切 - Promise.all() (您正在使用箭头函数,因此我认为 native Promise 也适合您)。它接受一组 Promise 并返回一个 Promise,该 Promise 在所有数组的 Promise 完成执行时解析。 (如果其中任何一个错误,则立即拒绝)。 .then 函数将被赋予一个数组,表示每个 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 */);

尽管如此,我们仍然必须为每个想要点击的链接手动调用.push。那不行!让我们使用 Array.prototype.map 来实现一个绝妙的技巧。它将迭代我们的数组,依次操作每个值并返回一个由新值组成的新数组:

var arrayOfPromises = paths.map((path) => rp(`http://www.example.com/${path}`));
Promise.all(arrayOfPromises)
.then((arrayOfHtml) => arrayOfHtml.forEach(processStuff))
.catch(function (err) { console.log('agh!'); });

更清晰、更容易的错误处理。

关于node.js - Node.js 中 ForEach 内的异步请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33909097/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com