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

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

在 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()

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

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

另见 API-Reference

您可以使用模型 [1]

中的 attachRequestCompleted-listener
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]

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

检查 SAPUI5 上下文:SAPUI5 Wait for an Deferred-Object // wait for .done() function

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

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

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

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

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

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

您还可以使用方法链来简化此过程。

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

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 的上下文是如何变化的。

Event Provider API Reference

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

logLoadedData: <strong>async</strong> 函数 () {
  const jsonModel = new JSONModel();
  <strong>等待</strong> jsonModel.loadData("<em><主机></em>/data/config.json");
  console.log(jsonModel.getData()); // 在 loadData 承诺被解析之后
},

或者,还有 API dataLoaded 也是 returns 一个承诺。当 loadData 发送的所有请求都完成时,它将解决。这是没有 async-await 的语法:

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

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