JS视图填充表格出现Undefined值问题排查(调用Google Roads API)
问题排查与解决方案
我帮你分析下导致表格中speedlimit列显示undefined的核心原因,以及对应的修复方案:
核心问题分析
1. 异步AJAX的执行顺序问题
你在循环发起Google Roads API的异步请求后,立刻就执行了表格渲染代码。但AJAX请求是异步的——也就是说,表格渲染的时候,Google API的响应还没回来,speeddata里的speedlimits属性还没被赋值,所以表格里显示undefined。而你在控制台看到的speeddata是后来异步请求完成后更新的,所以看起来属性正确,但这时候表格已经渲染完了。
2. 循环中的闭包陷阱
你用var i声明循环变量,在Google API的success回调里访问的i是全局的循环变量,当异步回调执行时,循环已经结束,i的值是speeddata.length,这会导致赋值逻辑完全错误。
3. speedobject的赋值逻辑混乱
你每次Google API返回后,把限速数据push到speedobject,然后用forEach给speeddata的每一项赋值,这会导致后面的请求数据覆盖前面的,而且索引对应关系完全不对。
修复后的代码
我把代码改成用Promise来管理所有异步请求,确保所有限速数据都获取完成后再渲染表格,同时修复了闭包和赋值逻辑:
function getSpeedData() { // Getting dates from dates inputs and imei var start = $('#startDate').val(); var stop = $('#endDate').val(); var imei = parseInt($('#selectVehicles').val()); // Converting to needed format var newstart = moment(start, "DD/MM/YYYY").format("YYYY-MM-DD"); var newstop = moment(stop, "DD/MM/YYYY").format("YYYY-MM-DD"); // Getting data from back-end var roadsapikey = "**********"; var dburl = $('#getData').data('request-url'); var model = { start: newstart, end: newstop, imei: imei }; $.ajax({ url: dburl, dataType: 'json', type: 'GET', data: model, success: function (data) { if (data.length !== 0) { var speeddata = data; // 用Promise数组存储所有Google API请求 var apiPromises = []; speeddata.forEach((item, index) => { var path = "path=" + item.Latitude2 + ',' + item.Longitude2; var googleurl = "https://roads.googleapis.com/v1/speedLimits?" + path + "&key=" + roadsapikey; // 把每个AJAX请求包装成Promise var promise = new Promise((resolve, reject) => { $.ajax({ url: googleurl, dataType: 'json', type: 'GET', success: function (res) { // 直接给当前speeddata项赋值限速 if (res.speedLimits && res.speedLimits.length > 0) { item.speedlimits = res.speedLimits[0].speedLimit; } else { item.speedlimits = 'N/A'; // 处理无限速数据的情况 } resolve(); }, error: function() { item.speedlimits = 'Error'; // 处理请求失败的情况 reject(); } }); }); apiPromises.push(promise); }); // 等待所有API请求完成后再渲染表格 Promise.all(apiPromises).then(() => { console.log(speeddata); // 清空表格再渲染(避免重复添加) $('#speeddata').empty(); speeddata.forEach(item => { $('#speeddata').append(`<tr> <td>${item.Imei}</td> <td>${item.Latitude2}</td> <td>${item.Longitude2}</td> <td>${item.Speed}</td> <td>${item.speedlimits}</td> </tr>`); }); }).catch(() => { alert("部分限速数据获取失败"); }); } }, error: function () { alert("Error fetching vehicle data"); } }); }
关键修改点
- 用
Promise.all()等待所有Google Roads API请求完成后再渲染表格,确保数据已经被正确赋值。 - 改用
forEach循环遍历speeddata,避免闭包陷阱(也可以用let i代替var i来解决)。 - 直接在Google API的回调中给对应的
speeddata项添加speedlimits属性,去掉了混乱的speedobject数组。 - 添加了请求失败和无限速数据的处理逻辑,避免出现
undefined。 - 渲染表格前先清空表格,避免重复添加数据。
内容的提问来源于stack exchange,提问作者Yevhen
相关产品推荐
相关产品推荐

