ES3环境下如何等待所有Google Places API回调完成后处理结果?
解决ES3环境下Google Places API异步请求的批量回调问题
首先咱们拆解你遇到的两个核心问题:
- 闭包陷阱:循环里的
i是函数级共享变量,当getDetails的异步回调执行时,循环已经跑完,i早就变成了q(也就是7),所以每个回调里的i都是7,这就是你看到每次输出都是Loop is 7/7的原因。 - 错误的完成判断:你用
i === q触发完成回调,但这个条件在第一个回调执行时就满足了,导致每次请求完成都跑一遍callback1,根本没等到所有请求结束。
针对ES3环境(不能用Promise、let/const),咱们可以用闭包保存循环索引+计数器跟踪完成状态的方案解决:
修正后的代码
var q; q = 7; if (uniqueGeoRes.length < q) { q = uniqueGeoRes.length; } uniqueGeoRes.length = q; var addrOutput = []; // 新增计数器,跟踪已完成的请求数量 var completedRequests = 0; //Check for additional Places data function updatePlace(arr, callback1){ console.log('asyncFunction has been called'); console.log('processing: ', arr); for (var i = 0; i < q; i++) { // 用立即执行函数(IIFE)创建闭包,保存当前循环的i值 (function(currentIndex) { // each element in the uniqueGeoRes array if (arr[currentIndex].source === 'Places API') { // 修复:把赋值=改成相等判断=== // Append extra information from the Place look up on individual place_id console.log('Getting additional information for PLACES result: ' + arr[currentIndex].place_id); var request = { placeId: arr[currentIndex].place_id, fields: ['address_component', 'formatted_address', 'geometry', 'name'] }; service.getDetails(request, function(place, status) { // Get the additional place information. if (status == google.maps.places.PlacesServiceStatus.OK) { addrOutput.push(place); console.log ('Loop is ' + (currentIndex + 1) + '/' + q + '. addrOutput length is now: ' + addrOutput.length); } else { console.warn ('Place Service Status is bad for index ' + currentIndex); } // 不管请求成功失败,计数器加1 completedRequests++; // 当所有请求都完成时,才触发最终回调 if (completedRequests === q) { callback1(null); // 按标准回调风格传错误参数,无错误则传null } }); } else { // 如果不是Places API的结果,也算完成一个请求 completedRequests++; if (completedRequests === q) { callback1(null); } } })(i); // 把当前循环的i传入IIFE,保存为独立的currentIndex } }; // Call when asyncFunction completes function callback1(error) { if (!error) { console.log('asyncFunction is complete'); console.log('Final addrOutput length: ', addrOutput.length); // 这里可以安全处理最终的addrOutput数组了 } } updatePlace(uniqueGeoRes, callback1);
关键改动说明
- 闭包保存循环索引:用立即执行函数(IIFE)把每次循环的
i封装成currentIndex,让每个异步回调都能拿到自己对应的索引值,避免所有回调共用最后一个i的问题。 - 计数器跟踪完成状态:新增
completedRequests变量,每次请求(无论成功失败)完成后都加1,只有当计数器等于总请求数q时,才触发最终的callback1,确保所有请求都处理完毕。 - 修复赋值错误:把
if (arr[i].source = 'Places API')的赋值操作=改成严格相等判断===,避免逻辑错误。 - 处理非Places结果:如果数组里有非Places API的元素,也要更新计数器,否则这些元素会导致永远触发不了完成回调。
预期输出效果
现在你会看到每个回调输出对应的索引(比如Loop is 1/7、Loop is 2/7...),直到最后一个请求完成后,只会输出一次asyncFunction is complete,此时addrOutput已经包含了所有成功获取的Places数据,可以放心处理。
内容的提问来源于stack exchange,提问作者TangoMike
相关产品推荐
相关产品推荐

