如何在 UI5 中等待 JSONModel.loadData() 请求

How to wait for a JSONModel.loadData() request in UI5

本文关键字:loadData 请求 JSONModel 等待 UI5      更新时间:2023-09-26

在SAPUI5/OpenUI5中,我有一个JSONModel,我用服务器中的文件填充:

var oModel = new JSONModel();
oModel.loadData("http://127.0.0.1/data/config.json");
console.log(JSON.stringify(oModel.getData()));

控制台记录undefined,因为请求是异步的.
如何使其同步,以便在加载数据后调用console.log()

不建议使用同步 ajax 请求,因为它会阻止 UI,并且可能会导致控制台中出现警告。

您可以附加到 Model.requestCompleted 事件以访问异步加载的数据:

oModel.attachRequestCompleted(function() {
        console.log(oModel.getData());
    });

您要查找的关键字是"延迟"对象 -->它使您能够在 SAPUI5 中等待 AJAX 请求。

检查 SAPUI5

上下文:SAPUI5 等待延迟对象//等待 .done() 函数

从 UI5 版本 1.64.0 开始,API loadData返回一个 Promise 实例:

logLoadedData: async function () {
  const jsonModel = new JSONModel();
  await jsonModel.loadData("<host>/data/config.json");
  console.log(jsonModel.getData()); // after the loadData promise is resolved
},

或者,还有返回承诺的 API dataLoaded。当loadData发送的所有请求都完成后,它将解决。下面是一个没有异步等待的语法:

doSomethingWith: async function (jsonModel) {
  // Not sure if the model has all data loaded? Just use dataLoaded:
  await jsonModel.dataLoaded();
  console.log(jsonModel.getData());
},

当使用字符串 (URL) 作为参数调用 JSONModel 的构造函数时,也会在内部调用 API loadData。在这种情况下,dataLoaded也可能派上用场。

你可以使用 Model 中的 attachRequestComplete-listener [1]

model.attachRequestCompleted(function(){
    console.log(this.getData()); //"this" is the model
});

另一个要使用的函数是

$.get(url, function(response){
    console.log(response);
    model.setData(response);
});
// or
$.ajax(url, {
    success: function(){
        console.log(response);
        model.setData(response);
    }
});

这样做的好处是,您可以使用 jQuery.ajax 接受的每个设置来配置请求 [2]

实现此目的的另一种方法是使用 EventProvider 中的 attachEventOnce 方法。

oModel.attachEventOnce("requestCompleted", function(oEvent) {
    console.log(JSON.parse(oEvent.getParameter("response").responseText));
}, this);

当您只需要对一个请求而不是所有请求做出反应时,最好使用此方法。否则,如果使用 oModel.attachRequestCompleted(...) ,则所有请求都将通过相同的处理程序函数。

您还可以使用方法链接来简化此操作。

oModel.attachEventOnce(...) 返回调用该方法的对象,因此您可以在一个语句中加载数据并处理回调。

oModel.attachEventOnce("requestCompleted", function(oEvent) {
    console.log(JSON.parse(oEvent.getParameter("response").responseText));
}, this).loadData("http://127.0.0.1/data/config.json");

这将首先执行loadData()请求,然后在请求完成后控制台响应。它只会在第一次发出请求时使用回调函数。后续请求不会通过回调函数。

如果您希望所有请求都通过相同的回调函数,则可以执行相同的操作,但使用oModel.attachRequestCompleted(...)

oModel.attachRequestCompleted(function(oEvent) {
    console.log(JSON.parse(oEvent.getParameter("response").responseText));
}, this).loadData("http://127.0.0.1/data/config.json");

这将执行loadData()请求,控制台响应,并控制台所有后续请求的响应。

注意:在回调函数中使用this时要小心。如果不将this作为attachRequestCompleted(...)attachEventOnce(...)方法的参数传递,则this将失去其作为控制器的原始上下文,并继承调用函数的对象的上下文。Herrlock的回答说明了this的背景是如何变化的。

事件提供程序 API 参考

原来.loadData()函数中有一个参数来创建同步调用:

oModel.loadData("http://127.0.0.1/data/config.json", "", false);

另请参阅 API 参考。