我正在尝试构建一个映射到给定数组的函数,然后在每个项目上运行axios调用。完成此操作后,我想返回映射的数组以在另一个函数中使用。
代码如下:
require('dotenv').config();
const axios = require('axios');
const consola = require('consola');
function getLeagues(listItems) {
const today = new Date();
const season = today.getMonth() >= 6 ? today.getFullYear() : today.getFullYear() - 1; // this gets the game ready for the new season every July 1st
// we will end up directly returning listItems.map once the issue is solved
const selectedLeagues = listItems.map(async (item) => {
const countryName = item.country;
const leagueName = item.league;
try {
const response = await axios({
method: 'GET',
url: `https://api-football-v1.p.rapidapi.com/v2/leagues/country/${countryName}/${season}`,
headers: {
'content-type': 'application/octet-stream',
'x-rapidapi-host': 'api-football-v1.p.rapidapi.com',
'x-rapidapi-key': process.env.FOOTY_API_KEY,
},
});
const leagueData = response.data.api.leagues
.filter((league) => league.name === leagueName)
.map((data) => {
return {
leagueId: data.league_id,
name: data.name,
seasonStart: data.season_start,
seasonEnd: data.season_end,
country: data.country,
};
})
.pop(); // we use pop() because filter() and map() return arrays and we don't want an array of 1 object, just that object
consola.ready({
// this displays all of the data as needed
// this also runs after the below consola block
message: `leagueData: ${JSON.stringify(leagueData, null, 2)}`,
badge: true,
});
return leagueData;
} catch (error) {
throw new Error(error);
}
});
consola.ready({
// this displays an array with an empty object, not an array with above leagueData object
// this also runs before the above consola block
message: `selectedLeagues: ${JSON.stringify(selectedLeagues, null, 2)}`,
badge: true,
});
return selectedLeagues;
}
module.exports = getLeagues;
我不确定为什么在selectedLeagues
对象尚未准备好之前就返回leagueData
数组。我以为异步/等待可以容纳一切。相反,在控制台中,我得到:
selectedLeagues: [
{}
]
leagueData: {
"leagueId": 753,
"name": "Liga 3",
"seasonStart": "2019-07-19",
"seasonEnd": "2020-05-16",
"country": "Germany"
}
我在做什么错了?
答案 0 :(得分:2)
不幸的是,listItems.map
与map
不兼容,因此您必须将async
包装在promise all函数中。
let results = Promise.all(listItems.map(item => {
// Then put your try catch here so that it only wraps around
// the results of the function you're awaiting...
let response
try {
response = await axios()
} catch (err) {
console.log(err)
}
// Anything else you want to do with the response...
}))
当您在异步函数中使用await
关键字时,其余代码将仅等待等待函数的结果,try catch部分是捕获您可能无法控制的任何错误。这就是为什么您只尝试抓住等待的功能。
如果将太多代码包装在try catch中,则将无法正确诊断和处理错误。
如果愿意,可以尝试遍历整个代码,但是问题是,只要有任何小问题,整个代码就会出错。
您也可以使用for循环来执行此操作,这看起来可能更干净...
for await (let item of listItems) {
// try catch await axios etc...
}
答案 1 :(得分:0)
您的.map()
中发生的是异步的,而不是外部的。 .map()
开始,但不会阻塞底部的consola.ready({
。
答案 2 :(得分:0)
您可以将异步与 Promise 结合使用,
const arr = [1, 2, 3];
const asyncRes = await Promise.all(arr.map(async (i) => {
await sleep(10);
return i + 1;
}));
console.log(asyncRes);
// 2,3,4