SAPUI5中如何异步处理LocalStorage避免对话框打开延迟?
解决SAPUI5中LocalStorage操作导致对话框打开延迟的问题
嘿,这个问题我碰到过!LocalStorage本身是同步API,如果序列化的数据量比较大(比如你用CircularJSON.stringify处理复杂的binding context或者大对象),会阻塞浏览器的主线程——哪怕你把存储代码放在_oDetailsDialog.open()之后,主线程还是得先完成序列化和存储操作,才能继续处理对话框的渲染,这就导致了延迟。
下面给你几个异步处理的方案,让对话框能立刻打开,存储操作在后台完成:
方案1:用setTimeout把存储操作放到事件循环的下一轮
这是最简单的异步处理方式,把LocalStorage操作包在setTimeout里(延迟0秒就行),让浏览器先完成对话框的渲染,再执行存储:
onClickAssignment: function(oEvent) { var oAppointment = oEvent.getParameter("appointment"); this.lastAppointment = oAppointment; if (oAppointment) { var key = this.byId("PC1").getViewKey(); if (key === "Month") { if (!this._oDetailsDialog || this._oDetailsDialog === null) { // show assignment dialog this._oDetailsDialog = sap.ui.xmlfragment(this.fragmentDetailsId, "be.xxxxxxxxxxx.fragment.viewAssignment", this); this.getView().addDependent(this._oDetailsDialog); } } else { if (!this._oDetailsDialog || this._oDetailsDialog === null) { // show subassignment dialog this._oDetailsDialog = sap.ui.xmlfragment(this.fragmentDetailsId, "be.xxxxxxxxxxx.fragment.viewSubassignment", this); this.getView().addDependent(this._oDetailsDialog); } } this.oAppBC = oAppointment.getBindingContext(); this._oDetailsDialog.setBindingContext(this.oAppBC); this._oDetailsDialog.open(); this.lastClickedAssignment = oAppointment.getProperty("assignment"); this.lastClickedSubassignment = oAppointment.getProperty("subassignment"); // 异步执行LocalStorage操作 setTimeout(() => { const stringifiedContext = CircularJSON.stringify(oAppointment.getBindingContext()); const stringifiedAssignment = CircularJSON.stringify(oAppointment.getProperty("assignment")); const stringifiedSubassignment = CircularJSON.stringify(oAppointment.getProperty("subassignment")); this.setLocalStorage("context", stringifiedContext); this.setLocalStorage("assignment", stringifiedAssignment); this.setLocalStorage("subassignment", stringifiedSubassignment); }, 0); } }
方案2:用requestIdleCallback利用浏览器空闲时间
如果你想更高效一点,可以用requestIdleCallback——它会在浏览器有空闲资源的时候才执行存储操作,完全不会影响UI响应:
// 替换上面的setTimeout部分 requestIdleCallback(() => { const stringifiedContext = CircularJSON.stringify(oAppointment.getBindingContext()); const stringifiedAssignment = CircularJSON.stringify(oAppointment.getProperty("assignment")); const stringifiedSubassignment = CircularJSON.stringify(oAppointment.getProperty("subassignment")); this.setLocalStorage("context", stringifiedContext); this.setLocalStorage("assignment", stringifiedAssignment); this.setLocalStorage("subassignment", stringifiedSubassignment); });
额外优化:减少序列化的数据量
除了异步处理,你还可以优化序列化的内容——如果不需要存储整个binding context或者assignment对象,只提取你需要的字段,这样序列化的速度会快很多,甚至同步执行也不会卡:
// 示例:只存储需要的关键字段,而不是整个对象 requestIdleCallback(() => { // 简化binding context数据 const bcPath = this.oAppBC.getPath(); const bcModel = this.oAppBC.getModel().getName(); const simplifiedContext = JSON.stringify({ path: bcPath, model: bcModel }); // 简化assignment数据 const assignment = oAppointment.getProperty("assignment"); const simplifiedAssignment = JSON.stringify({ id: assignment.id, title: assignment.title, // 只保留你后续需要用到的字段 }); this.setLocalStorage("context", simplifiedContext); this.setLocalStorage("assignment", simplifiedAssignment); // ...其他存储操作 });
这样既减少了LocalStorage的存储空间,又提升了序列化的速度,双重优化性能。
内容的提问来源于stack exchange,提问作者Matthijs Mennens
相关产品推荐
相关产品推荐

