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

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);

问题根源:异步操作的执行顺序不对!

你遇到的是前端开发中非常常见的异步回调时机问题,我给你拆解下代码的执行流程:

  1. 先初始化datelist为一个空数组
  2. 创建JSONModel并绑定requestCompleted事件回调——注意,这个回调只有在请求完成后才会触发,现在只是“预约”了这个函数
  3. 立刻执行两次console.log(datelist)——这时候oModel.loadData()刚被调用,HTTP请求还在后台跑呢,回调函数根本没执行,datelist当然还是空的,length就是0
  4. 等浏览器把请求发出去、拿到响应后,才会触发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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:56:21