为何控制台显示数组所有元素但length返回0?AJAX异步问题求助
搞定AJAX异步导致数组长度为0的问题
兄弟,你遇到的这个坑其实是AJAX的异步特性在搞事情!我来给你拆解清楚:
问题根源:代码执行顺序不对
AJAX请求是异步的——简单说就是,当你的代码执行到$.ajax(...)这一行时,浏览器会把这个请求丢到后台去跑,然后立刻继续往下执行后面的console.log(res.length)、循环这些代码。这时候then回调里的逻辑还完全没触发呢,res数组还是空的,所以res.length自然是0。
至于你后面看控制台console.log(res)能看到元素?那是浏览器控制台的小陷阱:它对数组、对象这种引用类型是惰性求值的,你当时打印的时候它其实是空的,但等AJAX请求完成、res被填充后,你在控制台展开这个数组,它才会显示最新的内容,这很容易误导人以为当时数组已经有数据了。
两种解决方案
方案1:把依赖res的代码全放到then回调里
既然要等AJAX请求完成、res被填充后才能用它,那直接把所有需要用到res的逻辑都塞进then回调里就行,确保顺序正确:
$.ajax({ url: "url", type : "GET", data : { firstDate : "date1", secondDate : "date2"} }).then(function(data) { var obj = JSON.parse(data); obj.results.forEach(element => { console.log(element.DATEEND); res.push(element); dates.push(element.DATESTART); }); // 所有依赖res的代码都移到这里 var days = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi']; var i; function min_date(all_dates) { var min_dt = all_dates[0], min_dtObj = new Date(all_dates[0]); all_dates.forEach(function(dt, index){ if ( new Date( dt ) < min_dtObj) { min_dt = dt; min_dtObj = new Date(dt); } }); return min_dt; } var d = []; console.log(res.length + " "); // 这里会正确返回数组长度 for (var a = 0; a < res.length; a++) { d[a] = res[a].DATESTART; console.log(res[a].DATESTART); } console.log(d); // 这里也会有数据了 console.log(res); });
方案2:用async/await改造成同步写法
如果觉得回调嵌套看着麻烦,可以用ES6的async/await把异步代码改成同步风格的写法,逻辑更清晰:
// 把所有逻辑放到async函数里 async function fetchAndProcessData() { try { // 等待AJAX请求完成,拿到数据 const data = await $.ajax({ url: "url", type : "GET", data : { firstDate : "date1", secondDate : "date2"} }); var obj = JSON.parse(data); obj.results.forEach(element => { console.log(element.DATEEND); res.push(element); dates.push(element.DATESTART); }); // 这里就可以正常使用res了,顺序和你写的一样 var days = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi']; var i; function min_date(all_dates) { var min_dt = all_dates[0], min_dtObj = new Date(all_dates[0]); all_dates.forEach(function(dt, index){ if ( new Date( dt ) < min_dtObj) { min_dt = dt; min_dtObj = new Date(dt); } }); return min_dt; } var d = []; console.log(res.length + " "); for (var a = 0; a < res.length; a++) { d[a] = res[a].DATESTART; console.log(res[a].DATESTART); } console.log(d); console.log(res); } catch (error) { // 别忘了处理请求失败的情况 console.error('请求出错啦:', error); } } // 调用这个函数 fetchAndProcessData();
这样改完之后,你就能正常获取到res的长度和里面的数据啦!
内容的提问来源于stack exchange,提问作者M.SAM SIM
相关产品推荐
相关产品推荐

