You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

关键改动说明

  1. 闭包保存循环索引:用立即执行函数(IIFE)把每次循环的i封装成currentIndex,让每个异步回调都能拿到自己对应的索引值,避免所有回调共用最后一个i的问题。
  2. 计数器跟踪完成状态:新增completedRequests变量,每次请求(无论成功失败)完成后都加1,只有当计数器等于总请求数q时,才触发最终的callback1,确保所有请求都处理完毕。
  3. 修复赋值错误:把if (arr[i].source = 'Places API')的赋值操作=改成严格相等判断===,避免逻辑错误。
  4. 处理非Places结果:如果数组里有非Places API的元素,也要更新计数器,否则这些元素会导致永远触发不了完成回调。

预期输出效果

现在你会看到每个回调输出对应的索引(比如Loop is 1/7、Loop is 2/7...),直到最后一个请求完成后,只会输出一次asyncFunction is complete,此时addrOutput已经包含了所有成功获取的Places数据,可以放心处理。

内容的提问来源于stack exchange,提问作者TangoMike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:27:28