Using async/await for promise-based APIs in UI5

4.5k views Asked by At

The official UI5 documentation proposes to load a Fragment using promises:

Fragment.load({
    controller: oFragmentController,
        id: oView.getId(),
        name: "webapp.view.HelloDialog"
    }).then((oDialog) => {

    oView.addDependent(oDialog);

    oDialog.open();

});

I personally would prefer to use async/await instead:

const oDialog = await Fragment.load({
    controller: oFragmentController,
    id: oView.getId(),
    name: "webapp.view.HelloDialog"
});

oView.addDependent(oDialog);

oDialog.open();

How save would be such code refactoring and transition from .then-promises to async/await in UI5? Can it lead to some issues?

2

There are 2 answers

0
Boghyon Hoffmann On BEST ANSWER

You can safely use asyncawait in UI5 since it's basically syntactic sugar for Promise with some restrictions currently. *

Given <Dialog id="helloDialog"> in the fragment definition, and this being the current controller instance, creating the fragment would then look like this:

With this.loadFragment (since UI5 1.93)

// this === Controller instance
onOpenDialog: async function() {
  const dialog = this.byId("helloDialog") || await this.loadFragment({
    name: "webapp.view.HelloDialog"
  });
  dialog.open();
},

With Fragment.load (since UI5 1.58)

// this === Controller instance
// Fragment required from "sap/ui/core/Fragment"
onOpenDialog: async function() {
  let dialog = this.byId("helloDialog");
  if (!dialog) {
    dialog = await this.getOwnerComponent().runAsOwner(() => Fragment.load({
      id: this.getView().getId(),
      name: "webapp.view.HelloDialog",
      controller: this,
    }));
    this.getView().addDependent(dialog);
  }
  dialog.open();
},

The old factory function sap.ui.xmlfragment is deprecated and fetches the *.fragment.xml file synchronously.

That being said, if the app is targeting abandoned browsers such as the Internet Explorer, asyncawait should be avoided completely. Promise or then-able functions work in IE11 only because UI5 comes with a polyfill that gets applied if the Promise is not already natively or fully supported. **


* ... if the project is based on UI5 Tooling. See the newly introduced sections "Asynchronous Factory Function" and "Event Handler Registration" from the topic ECMAScript Support in UI5.

** IE11 is no longer supported. The polyfill is also removed accordingly.

0
Jorg On

Refactoring that is pretty easy, all you need to do in addition is flagging the method you're calling it from as async, which is really the only change you need to make.

The biggest potential issue you'll have is browser support, if you don't run your codebase through a tool like Babel. The biggest hurdle is IE 11, which many enterprise customers still use.

onFragmentLoad: async function(oEvent) {
  const oDialog = await Fragment.load({
    controller: this,
    id: this.getView().getId(),
    name: "webapp.view.HelloDialog"
  });

  this.getView().addDependent(oDialog);
}