JavaScript中API数据获取缓慢与空对象数组问题排查
问题分析与解决方案
函数1返回空数组的原因
getAllDogsData里的APIdata.map(async (dogs) => { ... })会返回一个Promise数组,但直接用await作用在这个数组上无效——数组本身不是Promise,await会直接返回原数组。此时你得到的dogsAPIData是一堆未解析的Promise,而非期望的犬种数据数组。如果调用者没再用Promise.all处理,就会呈现出类似空数组的结果。
函数2性能低下的原因
getAllDogsData2用for...of循环+内部await,导致图片请求串行执行:每完成一张图片请求,才会发起下一个。若有几十上百个犬种,总耗时就是所有图片请求时间的总和,自然会很慢。
修正与优化方案
1. 修复函数1的异步处理问题
用Promise.all()等待所有异步映射的Promise完成,即可得到解析后的完整数据数组:
const URL = "http://api.thedogapi.com/v1/breeds"; const IMAGES_URL = "https://api.thedogapi.com/v1/images"; const getAllDogsData = async () => { try { const response = await axios(`${URL}?api_key=${API_KEY}`); const APIdata = response.data; // 用Promise.all等待所有异步映射的Promise完成 const dogsAPIData = await Promise.all(APIdata.map(async (dog) => { // 先判断是否有图片ID,避免无效请求 let imageUrl = null; if (dog.reference_image_id) { imageUrl = await getDogImage(dog.reference_image_id); } return { id: dog.id, name: dog.name, average_weight: getProm(dog.weight.metric), average_height: getProm(dog.height.metric), life_span: dog.life_span, imageID: dog.reference_image_id, imageUrl, }; })); return dogsAPIData; } catch (error) { console.error("获取犬种数据失败:", error.message); throw error; } };
2. 优化图片请求性能(并行请求)
上面的修复已通过Promise.all实现并行请求,所有图片请求会同时发起,总耗时接近最慢的单个请求时间,而非所有请求时间的总和。
3. 健壮性优化
- 增加
reference_image_id判空:部分犬种可能没有图片ID,提前判断可避免无效请求报错。 - 给
getDogImage添加错误兜底:若某个图片请求失败,返回默认图片URL,避免整个Promise.all失败:
const getDogImage = async (id) => { try { const response = await axios(`${IMAGES_URL}/${id}`); return response.data.url; } catch (error) { console.error(`获取图片ID ${id} 失败:`, error.message); // 返回默认图片地址或null return "https://example.com/default-dog-image.jpg"; } };
4. 进阶优化:批量请求减少API调用
The Dog API支持批量获取图片,可将所有图片ID拼接成单个请求,把N次请求缩减为1次,大幅提升性能:
const getAllDogImages = async (imageIds) => { if (!imageIds.length) return {}; try { const response = await axios(`${IMAGES_URL}?ids=${imageIds.join(",")}`); // 转成ID->URL的映射表,方便后续查询 return response.data.reduce((map, img) => { map[img.id] = img.url; return map; }, {}); } catch (error) { console.error("批量获取图片失败:", error.message); return {}; } }; // 主函数中使用批量请求 const getAllDogsData = async () => { try { const response = await axios(`${URL}?api_key=${API_KEY}`); const APIdata = response.data; // 收集所有有效的图片ID const validImageIds = APIdata .map(dog => dog.reference_image_id) .filter(id => id); // 批量获取所有图片 const imageMap = await getAllDogImages(validImageIds); // 映射犬种数据,直接从映射表取图片URL const dogsAPIData = APIdata.map(dog => ({ id: dog.id, name: dog.name, average_weight: getProm(dog.weight.metric), average_height: getProm(dog.height.metric), life_span: dog.life_span, imageID: dog.reference_image_id, imageUrl: imageMap[dog.reference_image_id] || null, })); return dogsAPIData; } catch (error) { console.error("获取犬种数据失败:", error.message); throw error; } };
内容的提问来源于stack exchange,提问作者Birkenz
相关产品推荐
相关产品推荐

