如何在JS的fetch循环调用中使用首次fetch的返回结果?
解决Google Maps API二次调用的异步问题
先给你指出原代码里的几个致命问题:
response.json是方法,必须调用(加括号response.json())才会返回解析JSON的Promise,你现在只是传了方法引用,根本没执行解析- 嵌套循环里的fetch会陷入回调地狱,不仅代码难维护,还没法保证请求完成顺序,也没法统一处理所有请求的结果
- 没有错误处理,fetch遇到4xx/5xx这类HTTP错误不会自动抛出异常,会默默继续执行,出问题根本查不到原因
下面是用async/await+Promise.all()重构后的可运行代码,逻辑清晰,能正确批量处理二次请求:
// 把整个逻辑封装在async函数里 async function fetchAndRenderPlaces() { try { // 第一步:调用附近搜索API获取地点列表 const nearbyResponse = await fetch(googleMapsApi); // 检查请求是否成功,失败就抛出错误 if (!nearbyResponse.ok) throw new Error(`附近搜索请求失败: ${nearbyResponse.status}`); const nearbyData = await nearbyResponse.json(); // 第二步:生成所有详情请求的Promise数组 const detailRequests = nearbyData.results.map(async (place) => { // 先提取第一次请求里的基础数据 const basicInfo = { name: place.name, address: place.formatted_address, location: place.geometry.location // 其他你需要的基础字段 }; // 用Place ID发起二次请求获取详情 const detailResponse = await fetch(`你的详情API地址?place_id=${place.place_id}&key=你的API密钥`); if (!detailResponse.ok) throw new Error(`获取${place.name}详情失败: ${detailResponse.status}`); const detailData = await detailResponse.json(); // 合并基础数据和详情数据 return { ...basicInfo, phone: detailData.result.formatted_phone_number, website: detailData.result.website, rating: detailData.result.rating // 其他你需要的详情字段 }; }); // 等待所有详情请求完成,拿到所有合并后的完整数据 const allPlaces = await Promise.all(detailRequests); // 第三步:统一渲染所有数据到页面 allPlaces.forEach(place => { // 这里写你的DOM渲染逻辑,比如创建卡片插入页面 const placeCard = document.createElement('div'); placeCard.innerHTML = ` <h3>${place.name}</h3> <p>${place.address}</p> <p>电话: ${place.phone || '无'}</p> <p>官网: ${place.website ? `<a href="${place.website}">点击访问</a>` : '无'}</p> `; document.body.appendChild(placeCard); }); } catch (err) { // 统一捕获所有错误,方便调试 console.error('处理请求时出错:', err.message); } } // 执行函数 fetchAndRenderPlaces();
核心逻辑说明:
- async/await:把异步代码写成同步风格,彻底摆脱嵌套回调的混乱,逻辑一目了然
- Promise.all():一次性发起所有二次请求,等待全部完成后再处理结果,比循环里逐个等效率高,也能保证所有数据都准备好再渲染
- 错误集中处理:用try/catch包裹所有异步操作,任何一步出错都会进入catch块,方便定位问题
- 数据合并:把第一次和第二次请求的数据合并成完整对象,再统一渲染,避免分散的DOM操作
原代码失效的根本原因:
JavaScript的异步特性会让循环里的fetch立即执行,不会等上一个请求完成,导致你可能在数据还没返回就试图渲染;加上response.json没加括号,根本没解析JSON,后续代码拿不到有效数据,自然没法正常运行。
内容的提问来源于stack exchange,提问作者Josh Watkins
相关产品推荐
相关产品推荐

