最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to wait for a JSONModel.loadData() request in UI5 - Stack Overflow

programmeradmin1浏览0评论

In SAPUI5/OpenUI5, I have a JSONModel I populate by a file from server:

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

The console logs undefined since the request is asynchronous.
How to make it synchronous so console.log() is called after the data was loaded?

In SAPUI5/OpenUI5, I have a JSONModel I populate by a file from server:

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

The console logs undefined since the request is asynchronous.
How to make it synchronous so console.log() is called after the data was loaded?

Share Improve this question edited Oct 18, 2021 at 13:05 Mike 14.6k31 gold badges119 silver badges176 bronze badges asked Jan 20, 2016 at 14:26 BenvorthBenvorth 7,7228 gold badges53 silver badges73 bronze badges 1
  • 1 For readers using UI5 version 1.64 and above: now loadData returns a promise. – Boghyon Hoffmann Commented Sep 14, 2020 at 22:02
Add a comment  | 

6 Answers 6

Reset to default 20

Using synchronous ajax requests is not recommended as it blocks the UI and will probably result in a warning in the console.

You can attach to the Model.requestCompleted event to access the asynchronously loaded data:

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

The keyword you are looking for is "Deferred"-object --> it enables you to wait for an AJAX request in SAPUI5.

Check this for SAPUI5 context: SAPUI5 Wait for an Deferred-Object // wait for .done() function

Since UI5 version 1.64.0, the API loadData returns a Promise instance:

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

Alternatively, there is also the API dataLoaded which returns a promise as well. It will resolve when all requests sent by loadData are finished. Here is a syntax without 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());
},

The API loadData is also called internally when the constructor function of JSONModel was called with a string (URL) as an argument. In that case, dataLoaded might come in handy as well.

You can use the attachRequestCompleted-listener from the Model [1]

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

Another function to use is

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

This has the advantage that you can configure the request with every setting that jQuery.ajax accepts [2]

Another way to achieve this is to use the attachEventOnce method from EventProvider.

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

It's best to use this approach when you only need to react to one request, and not all. Otherwise, if you use oModel.attachRequestCompleted(...), all requests will go through the same handler function.

You can also use method chaining to make this a little easier.

oModel.attachEventOnce(...) returns the object that called the method, so you can load your data and handle the callback all in one statement.

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

This will first execute the loadData() request, and then console the response when the request has been completed. It will only use the callback function the first time a request is made. Subsequent requests will not go through the callback function.

If you want ALL requests to go through the SAME callback function, you can do the same thing but using oModel.attachRequestCompleted(...)

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

This will execute the loadData() request, console the response, and also console the response of all subsequent requests.

NOTE: Be careful using this in the callback functions. If you don't pass this as a parameter of the attachRequestCompleted(...) or attachEventOnce(...) methods, then this will lose it's original context as the controller, and inherit the context of the object calling the function. herrlock's answer demonstrates how the context of this changes.

Event Provider API Reference

Turned out there is a parameter in the .loadData() function to create a sync- call:

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

See API-Reference as well.

发布评论

评论列表(0)

  1. 暂无评论