SAPUI5异步函数取值问题:数组含元素但length为0
为啥数组明明有10个元素,length却显示0?这是异步请求的坑!
先看你贴的代码:
var datelist = []; var oModel = new sap.ui.model.json.JSONModel(); oModel.attachRequestCompleted(function() { var oFeiertageBerlin = oModel.getData().BE; for (var prop in oFeiertageBerlin) { datelist.push(oFeiertageBerlin[prop].datum); } }); console.log(datelist); var jDatum = new Date(); var jLink = "https://feiertage-api.de/api/?jahr=" + jDatum.getFullYear(); oModel.loadData(jLink); // 为何此处datelist.length == 0? console.log(datelist, datelist.length);
问题根源:异步操作的执行顺序不对!
你遇到的是前端开发中非常常见的异步回调时机问题,我给你拆解下代码的执行流程:
- 先初始化
datelist为一个空数组 - 创建JSONModel并绑定
requestCompleted事件回调——注意,这个回调只有在请求完成后才会触发,现在只是“预约”了这个函数 - 立刻执行两次
console.log(datelist)——这时候oModel.loadData()刚被调用,HTTP请求还在后台跑呢,回调函数根本没执行,datelist当然还是空的,length就是0 - 等浏览器把请求发出去、拿到响应后,才会触发
attachRequestCompleted的回调,把10个元素push进datelist
为啥控制台里能看到数组有元素?
这是浏览器控制台的一个“小陷阱”:控制台显示的对象是动态引用,不是执行console.log时的快照。当你在控制台展开数组的时候,它才会去读取当前数组的实际内容——这时候回调已经执行完,数组已经被填充了,所以你看到有10个元素,但当时console.log执行的时候,数组确实是空的。
解决方案:把依赖datelist的逻辑放进回调里
所有需要用到datelist的代码,都必须等到请求完成、回调执行后再运行,最简单的方式就是把逻辑写在attachRequestCompleted的回调函数内部:
var datelist = []; var oModel = new sap.ui.model.json.JSONModel(); oModel.attachRequestCompleted(function() { var oFeiertageBerlin = oModel.getData().BE; for (var prop in oFeiertageBerlin) { datelist.push(oFeiertageBerlin[prop].datum); } // 所有需要用datelist的操作都放这里 console.log(datelist, datelist.length); // 这里就能得到正确的length(10)了 }); var jDatum = new Date(); var jLink = "https://feiertage-api.de/api/?jahr=" + jDatum.getFullYear(); oModel.loadData(jLink);
如果你的代码逻辑比较复杂,不想都堆在回调里,也可以用Promise封装异步操作,配合async/await让代码逻辑更线性(需要UI5版本支持):
async function loadHolidayDates() { let datelist = []; const oModel = new sap.ui.model.json.JSONModel(); const currentYear = new Date().getFullYear(); const requestUrl = `https://feiertage-api.de/api/?jahr=${currentYear}`; // 把loadData的异步操作转换成Promise await new Promise(resolve => { oModel.attachRequestCompleted(resolve); oModel.loadData(requestUrl); }); // 现在请求已经完成,可以安全处理数据了 const berlinHolidays = oModel.getData().BE; for (const key in berlinHolidays) { datelist.push(berlinHolidays[key].datum); } console.log(datelist, datelist.length); // length正确为10 } // 调用函数 loadHolidayDates();
内容的提问来源于stack exchange,提问作者Roman11222
相关产品推荐
相关产品推荐

