Skip to Content
Author's profile photo Arnd vom Hofe

UI5ers Buzz #29: Asynchronify your App

Asynchronous loading is one of the main drivers for improving the performance of your UI5 application. With asynchronous loading files are retrieved quickly in parallel.
Synchronous loading, on the other hand, fetches each file sequentially. This makes synchronous requests much slower and can even delay important tasks in the browser. The app will not respond to user interaction until the request is completed.

To avoid this, UI5 offers several areas where asynchronous behavior can be switched on and off.
The most prominent are of course setting data-sap-ui-preload=”async” in the bootstrap of the index.html and adding “async: true” to the creation of a sap.ui.component or a sap.ui.core.ComponentContainer.

But these are not the only places where this feature can speed up your app’s performance. Another very effective location for asynchronicity is the manifest.json, where you can enable asynchronous loading of views:

By adding “async”: true to the rootView section of sap.ui5, you ensure that the root view is loaded asynchronously.

"sap.ui5": {
  "rootView": {
    "viewName": "sap.ui.demo.worklist.view.App",
    "type": "XML",
    "async": true,
    "id": "app"
  },
  ...

For all other views just add an “async” flag to the config section of routing in sap.ui5

"sap.ui5": {
  ... 
  "routing": {
    "config": {
      "routerClass": "sap.m.routing.Router",
      "async": true,
      "viewType": "XML",
      "viewPath": "sap.ui.demo.worklist.view",
      ...
    },
 ...

In preparation for upcoming changes that are part of the UI5 Evolution process, we also recommend that you refactor your code:
Simply follow the new asynchronous module definition syntax to get rid of synchronous APIs.

This means that you should not use jQuery.sap.declare and jQuery.sap.require any longer, because they load and evaluate modules synchronously.

We recommend to use sap.ui.define or sap.ui.require instead, so that you don’t have to rely on global namespaces or lazy library loading.

Here is a small example on how such a refactoring could look like:

Within the UI5 framework there are some functionalities where synchronous requests are used internally. For most of them you can already use asynchronous alternatives in shape of JavaScript Promises, or you can change the synchronous behavior as shown below.

Whenever you want to load something after instantiating the UI5 app, add the async flag and run the code in the then part of the Promise.

Example: The loading of an additional library

    sap.ui.getCore().loadLibrary("sap.m")

should be written as

    sap.ui.getCore().loadLibrary("sap.m", {
     async: true
    }).then(
     ...
    );

Another example: The request of a resource bundle

    var oBundle = jQuery.sap.resources({ 
     url: "mybundle.properties" 
    }); 

can be improved by

   jQuery.sap.resources({ 
     url: "mybundle.properties", 
     async: true 
    }).then(function(oBundle) { ... }); 

At first it might look like lots of work to refactor existing code to asynchronous behavior. But it will be worth it! By transforming the modules you can make sure that you benefit from future enhancements of the UI5 evolution.

Previous Post: UI5ers Buzz #28

Have a great day,

Arnd

Arnd is an Expert Developer at SAP. He discovered the art of programming on pocket calculators, legacy home computers and game consoles. Today his focus is mainly on Web development technologies and UI5.

 

Assigned Tags

      3 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Andrej Kabachnik
      Andrej Kabachnik

      I've tried to configure the asynchronous view loading as shown above, but it still produces synchronous XHRs via loadSyncXHR() if the views are not packed into Component-preload.js. Is this intended?

      Author's profile photo Arnd vom Hofe
      Arnd vom Hofe
      Blog Post Author

      Sorry to hear that 🙁
      I am not sure, why this is happening to you. Without any code this won't be easy to solve. Could you provide some sort of example (e.g. Plunker)?

      Author's profile photo Boghyon Hoffmann
      Boghyon Hoffmann

      The loadSyncXHR might be triggered by the remaining APIs which don't have any asynchronous alternative yet. For example:

      • LocaleData, while being instantiated, fetches the CLDR file still synchronously: issue#2345.
      • sap/ui/core/Fragment.load is not async: issue#2462 (FIXED since 1.84).
      • Embedded views are loaded with sync XHR: issue#3112 (FIXED since 1.89 if UIComponent implements the sap.ui.core.IAsyncContentCreation interface).
      • Models loaded with preload: true require sap/ui/thirdparty/* synchronously: issue#3134.
      • JS resources declared in the descriptor (manifest.json) section /sap.ui5/resources/js are fetched synchronously: issue#3137  (FIXED but also deprecated since 1.94).
      • Core.createComponent has no async option: issue#3339 (That API should be rather deprecated IMHO).

      As mentioned by Arnd, a minimal reproducible example would help us greatly finding the issue quickly.