javascript - 如何在 Web 抓取时使用 Promise 和 async/await 发出多个嵌套的 http 请求
问题描述
下面我有一个 Node.js 函数,它向不同的 url 发出一系列请求,然后对于每个 url,我使用 Cheerio 网络抓取库循环遍历 dom 上的元素并创建一个子数组。在每个请求结束时(在子数组已满之后),我想将该数组的内容推送到一个更大的数组中,该数组超出了请求范围。
我正在尝试的方法似乎不起作用。看起来我无法从 .then 块内访问“allPlayers”。
function readPlayers(teamUrls){
const allPlayers = [];
teamUrls.forEach((teamUrl, i) => {
const options = {
gzip: true,
uri: teamUrl,
Connection: 'keep-alive',
transform: function (body) {
return cheerio.load(body);
}
};
request(options)
.then(($) => {
const team = [];
$('tbody').children('tr').each(function(j, element){
const playerName = $(element).children('td').eq(1).children('span').eq(1).find('a').text().trim();
const player = { 'playerName': playerName };
team.push(player);
});
allPlayers.push(team);
}).catch(err => console.log("error: " + err)) );
});
}
所以我想知道重写此代码以使请求工作并用结果填充外部数组(allPlayers)的最佳方法。
我已经考虑尝试将整个请求直接推送到外部数组中,但无济于事。
在这个例子中,我使用 request-promise 来发出请求。
我已经研究过使用 Promise.map,我认为它适合这种情况。然后我会返回整个请求(我认为),但我不完全理解在这种情况下我在做什么......或者它是否会起作用。
任何人都可以解释这种情况下的范围,为什么我不能像我正在尝试的那样做。
非常感谢
解决方案
您必须记住,当您使用异步函数时,您无法返回到同步代码执行。
这是您可以做到的方法之一。它将并行获取所有玩家:
async function readPlayers(teamUrls) {
const playerPromises = teamUrls.map((teamUrl, i) => {
const options = {
gzip: true,
uri: teamUrl,
Connection: 'keep-alive',
transform: function(body) {
return cheerio.load(body);
}
};
return request(options)
});
const players = await Promise.all(playerPromises);
return players.reduce((allPlayers, $) =>{
const team = [];
$('tbody').children('tr').each(function(j, element) {
const playerName = $(element).children('td').eq(1).children('span').eq(1).find('a').text().trim();
const player = { playerName: playerName };
team.push(player);
});
allPlayers.push(team);
return allPlayers;
},[])
}
你可以使用它await readPlayers(array)
或readPlayers(array).then(allteamplayers=>{...})
注意:在当前代码中,它将是一个二维数组,[[{p1:p1}..], [{p2:p2}..]] 等
推荐阅读
- php - 发送 ajax 发布请求,但 PHP 中的 $_POST 始终为空
- android - Html.from HTML 没有格式化 html 标签
- typescript - VueJS - 给 this.$refs 一个类型以删除 Typescript 错误
- python - 如何通过数据集中python中的加权概率获得均匀分布?
- angular - 哪种方式更适合我的登录表单位于我的角度材料 sidenav 之外
- operating-system - 需要解释问题的循环调度吗?
- php - 如何将 recaptcha v3 添加到 php 联系表单?
- r - 创建具有相同范围的多个密度图
- javascript - 在材质 ui 选项卡中使用效果隐藏第三个选项卡
- azure-ad-b2c - 如何确定 Azure AD B2C 中使用的身份验证方法?