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

JS循环填充数组问题:调用谷歌道路API后speedobject数据重复

问题分析与解决方案:循环调用谷歌道路API导致重复数据的问题

Hey there, let's break down why you're getting 36 duplicate entries instead of 6, and how to fix it:

核心问题原因

1. 全局变量path导致所有请求复用最后一个坐标

你代码里的path = "path=" + speeddata[i].Latitude2 + ',' + speeddata[i].Longitude2;没有用var/let声明,使得path成为全局变量。

  • for循环是同步执行的,会在瞬间完成6次迭代,每次覆盖全局的path值。
  • 而AJAX请求是异步的,当请求真正发送时,path已经被更新为最后一条数据的坐标,导致6个请求都在请求同一个位置的限速,返回重复数据。

2. var变量的作用域冲突

外层循环用var i声明循环变量,var是函数级作用域,所有AJAX回调会共享同一个i变量。虽然这个问题被全局path的问题掩盖,但也是潜在的逻辑隐患,可能导致后续关联原数据时出错。

3. 无统一的异步结果处理

你直接往全局的speedobject里push数据,且在每个回调里打印/render,导致每次请求完成都往数组里加数据,如果多个请求返回重复的限速条目,最终就会累积出36条数据。


修复方案

1. 改用局部变量避免全局污染

把path和循环变量改为块级作用域的局部变量,确保每次迭代的变量独立:

// 外层循环用let声明i,确保每次迭代的i是独立的
for (let i = 0; i < speeddata.length; i++) {
  // 用const声明path,避免全局污染
  const path = "path=" + speeddata[i].Latitude2 + ',' + speeddata[i].Longitude2;
  const googleurl = "https://roads.googleapis.com/v1/speedLimits?" + path + "&key=" + roadsapikey;
  
  $.ajax({
    url: googleurl,
    dataType: 'json',
    type: 'GET',
    success: function (data) {
      // 把内部循环变量改为j,避免和外层i冲突
      for (let j = 0; j < data.speedLimits.length; j++) {
        speedobject.push({ 
          speedlimits: data.speedLimits[j].speedLimit,
          // 可选:关联原数据的坐标、速度,方便后续表格渲染
          latitude: speeddata[i].Latitude2,
          longitude: speeddata[i].Longitude2,
          originalSpeed: speeddata[i].Speed
        });
      }
    },
    error: function () {
      alert("获取限速数据失败");
    }
  });
}

2. 用Promise.all统一处理异步请求(推荐)

如果需要确保所有请求完成后再渲染表格,避免多次渲染重复数据,可以把每个AJAX请求包装成Promise,统一等待所有请求完成:

// 先清空全局数组
speedobject = [];

// 把每个请求转为Promise
const requestPromises = speeddata.map(item => {
  const path = "path=" + item.Latitude2 + ',' + item.Longitude2;
  const googleurl = "https://roads.googleapis.com/v1/speedLimits?" + path + "&key=" + roadsapikey;
  
  return new Promise((resolve, reject) => {
    $.ajax({
      url: googleurl,
      dataType: 'json',
      type: 'GET',
      success: (data) => {
        // 假设每个坐标对应一个限速,取第一个结果即可
        const speedLimit = data.speedLimits.length > 0 ? data.speedLimits[0].speedLimit : null;
        // 把原数据和限速整合后返回
        resolve({
          ...item,
          speedlimits: speedLimit
        });
      },
      error: (err) => {
        reject(err);
      }
    });
  });
});

// 等待所有请求完成后再处理数据
Promise.all(requestPromises)
  .then(results => {
    speedobject = results;
    console.log(speedobject); // 此时数组会有6条唯一的对应数据
    // 在这里统一渲染表格
    renderSpeedTable(speedobject);
  })
  .catch(err => {
    alert("获取限速数据出错:" + err.message);
  });

3. 检查谷歌API返回结果

确认每个请求返回的data.speedLimits是否符合预期,如果某个坐标返回多个限速条目,需要根据业务逻辑筛选(比如取第一个、匹配当前道路的限速),避免不必要的重复push。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:01:30