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
相关产品推荐
相关产品推荐

