解决循环中await报错:await仅在async函数与模块顶层有效
解决forEach循环中使用await导致的报错问题
问题原因
你遇到的报错await is only valid in async functions and the top level bodies of modules,核心原因是forEach的回调函数并非异步函数,而await只能在标记为async的函数内部使用,普通forEach回调不满足这个执行条件。
另外你的代码还有两处细节问题需要修正:
getCountry函数里的axios.get重复拼接了URL,且没有返回请求结果,导致后续无法获取有效国家信息- API调用时重复写了URL,可直接复用配置对象里的
url字段
解决方案
方案1:使用for...of循环(串行执行请求)
把forEach替换成for...of循环,循环体处于GetDogs这个async函数的作用域内,可直接使用await,实现串行请求(前一个请求完成后再发起下一个):
const axios = require('axios').default; async function getCountry(breed) { const countryOptions = { method: 'GET', url: `https://countries-cities.p.rapidapi.com/location/country/${breed.origin}`, headers: { 'X-RapidAPI-Key': 'SECRET', 'X-RapidAPI-Host': 'countries-cities.p.rapidapi.com' } }; // 返回请求结果供上层使用 const response = await axios(countryOptions); return response.data; } async function GetDogs() { try { const options = { method: 'GET', url: 'https://dog-breeds2.p.rapidapi.com/dog_breeds', params: { limit: '2' }, headers: { 'X-RapidAPI-Key': 'SECRET', 'X-RapidAPI-Host': 'dog-breeds2.p.rapidapi.com' } }; const dogBreeds = await axios(options); // 用for...of替代forEach,直接使用await for (const breed of dogBreeds.data) { const country = await getCountry(breed); console.log(`犬种${breed.name}的原产国信息:`, country); } } catch (err) { console.error('请求出错:', err); } }; GetDogs();
方案2:给forEach回调添加async(并行执行请求)
如果希望提升效率,同时发起所有国家信息请求,可以给forEach的回调加上async,再用Promise.all收集并等待所有请求完成:
const axios = require('axios').default; async function getCountry(breed) { const countryOptions = { method: 'GET', url: `https://countries-cities.p.rapidapi.com/location/country/${breed.origin}`, headers: { 'X-RapidAPI-Key': 'SECRET', 'X-RapidAPI-Host': 'countries-cities.p.rapidapi.com' } }; const response = await axios(countryOptions); // 返回犬种名称与对应国家信息,方便后续关联 return { breedName: breed.name, countryInfo: response.data }; } async function GetDogs() { try { const options = { method: 'GET', url: 'https://dog-breeds2.p.rapidapi.com/dog_breeds', params: { limit: '2' }, headers: { 'X-RapidAPI-Key': 'SECRET', 'X-RapidAPI-Host': 'dog-breeds2.p.rapidapi.com' } }; const dogBreeds = await axios(options); // 收集所有请求的Promise实例 const countryPromises = []; dogBreeds.data.forEach((breed) => { countryPromises.push(getCountry(breed)); }); // 等待所有并行请求完成 const results = await Promise.all(countryPromises); results.forEach(result => { console.log(`犬种${result.breedName}的原产国信息:`, result.countryInfo); }); } catch (err) { console.error('请求出错:', err); } }; GetDogs();
关键说明
- 方案1适合API有请求频率限制的场景,串行执行不会触发限流
- 方案2效率更高,但要注意API的并发请求限制,避免因请求过多被拦截
- 修正了
getCountry的返回逻辑,确保能拿到有效数据 - 使用模板字符串
${}替代字符串拼接,提升代码可读性
内容的提问来源于stack exchange,提问作者Ole Dybedokken
相关产品推荐
相关产品推荐

