如何让JavaScript循环执行完毕后再进入下一轮循环?(Google Maps API场景)
嘿,我看你是想先把所有地点结果都处理妥当,再去跑后续的循环对吧?结合你给的代码,我分两种常见场景给你解决思路:
场景1:确保当前返回的所有results都处理完(不管同步/异步)
如果你的createMarker_Original是纯同步操作(比如只是创建Marker,没涉及异步加载照片这类操作),那原代码的for循环其实已经是把所有results处理完才会退出的。但如果createMarker_Original里有异步逻辑(比如加载照片的请求),那你得用Promise来等待所有异步操作都完成:
改造步骤:
- 把
createMarker_Original改成返回Promise的函数:
function createMarker_Original(place) { return new Promise((resolve, reject) => { const photos = place.photos; if (!photos) { resolve(); // 没照片直接标记完成 return; } const placeLoc = place.geometry.location; const marker = new google.maps.Marker({ position: placeLoc, map: map // 假设你有全局的map实例 }); // 举个例子:如果要异步加载照片缩略图 photos[0].getUrl({maxWidth: 100}).then(url => { // 给Marker加信息窗口之类的操作 const infowindow = new google.maps.InfoWindow({ content: `<img src="${url}" alt="${place.name}">` }); marker.addListener('click', () => infowindow.open(map, marker)); resolve(); // 异步操作完成,标记Promise成功 }).catch(err => { console.error('加载照片出错:', err); resolve(); // 就算失败也标记完成,避免卡住后续流程 }); }); }
- 改造
callback_Original,用Promise.all等待所有Marker处理完毕:
async function callback_Original(results, status) { if (status === google.maps.places.PlacesServiceStatus.OK) { // 把每个地点的处理任务转成Promise,收集起来 const markerTasks = results.map(place => createMarker_Original(place)); // 等待所有Promise完成——也就是所有地点都处理完了 await Promise.all(markerTasks); // 到这里,所有结果处理完毕!可以放心执行你的其他循环了 console.log('所有Marker都搞定了,开始跑后续逻辑'); // 比如你的其他循环代码: // for (let i = 0; i < someArray.length; i++) { ... } } }
场景2:解决“仅返回少量地点”的问题(获取所有分页结果)
如果你的问题是PlacesService只返回了第一页的结果(最多20个),而你需要拿到所有符合条件的地点,那得利用Google Places API的nextPageToken来分页获取所有结果,然后统一处理:
完整改造代码:
// 用来存所有拿到的地点 let allPlaces = []; // 递归/循环获取所有分页结果的函数 function fetchAllPlaces(service, request) { return new Promise((resolve, reject) => { service.nearbySearch(request, (results, status, pagination) => { if (status === google.maps.places.PlacesServiceStatus.OK) { // 把当前页的结果加到总数组里 allPlaces = [...allPlaces, ...results]; // 如果有下一页,继续获取(注意Google要求必须延迟200ms以上) if (pagination && pagination.hasNextPage) { setTimeout(() => pagination.nextPage(), 200); } else { // 所有页都拿完了,返回全部结果 resolve(allPlaces); } } else { reject(new Error(`获取地点失败:${status}`)); } }); }); } // 初始化搜索的入口函数 async function initPlaceSearch() { const map = new google.maps.Map(document.getElementById('map'), { center: {lat: -33.8688, lng: 151.2195}, // 示例坐标,换成你的 zoom: 13 }); const service = new google.maps.places.PlacesService(map); const searchRequest = { location: map.getCenter(), radius: 5000, type: ['restaurant'] // 换成你的搜索条件 }; try { // 先拿到所有分页的地点结果 const allResults = await fetchAllPlaces(service, searchRequest); console.log(`所有地点获取完成,一共${allResults.length}个`); // 统一处理所有结果,创建Marker const markerTasks = allResults.map(place => createMarker_Original(place)); await Promise.all(markerTasks); // 到这里,所有结果都处理完了!可以执行你的其他循环了 console.log('所有Marker创建完成,开始执行后续逻辑'); // 你的其他循环代码写在这里: // for (...) { ... } } catch (err) { console.error('流程出错:', err); } } // 调用初始化函数 initPlaceSearch(); // 同步版的createMarker_Original(如果不需要异步,也可以返回Promise方便统一处理) function createMarker_Original(place) { const photos = place.photos; if (!photos) { return Promise.resolve(); } const placeLoc = place.geometry.location; new google.maps.Marker({ position: placeLoc, map: map }); return Promise.resolve(); }
关键提醒:
- Google Places API要求分页调用必须间隔至少200ms,所以一定要加
setTimeout,不然会被拒绝请求 - 用
async/await和Promise可以完美实现“先处理完所有结果,再执行后续循环”的需求 - 如果你的
createMarker_Original是纯同步的,那直接循环处理也没问题,但用Promise统一处理的话,后续扩展异步逻辑更方便
内容的提问来源于stack exchange,提问作者MaeLstroms Stroms
相关产品推荐
相关产品推荐

