user2644620
user2644620

Reputation: 199

SAPUI5 how to provide Busy Indicator for POST call in for loop

I have an issue in displaying BusyIndicator for post call in for loop. Before posting this question i have explored all possible ways and didnt find any solution. Hence im posting here. Please apologize if this is silly question..

For one of the requirement, i have to call ODataModel POST call for 10 times in a for loop.

Here im able to get the results perfectly without any issue. But the problem is to fire all 10 services, it is taking nearly 20 seconds to finish execution of all services.

So i want to display BusyDialog before executing services. Below is my code..

                   var payload = {
                            "sectionIndex": 3,
                            "ratingType": "overall",
                            "userId": "",
                            "rating": "76",
                            "ratingKey": "wf_sect_3_rating"
                    };
                    //var busy = new sap.m.BusyDialog();
                    //busy.open();
                for (var i = 0; i < 10; i++) {
                    //var busy = new sap.m.BusyDialog();
                    //busy.open();

                    var that = this;
                    oModel.create("/URL", payload, {
                        success: function (oData, oResponse) {

                            if (oData.results[0].status === "OK") {
                                that.getView().getModel("employeesModel").refresh(true);
                            } else {
                                MessageBox.error("Error : " + oData.results[0].message);
                            }
                        },
                        error: function (e) {
                            MessageBox.error("Error : " + e);
                        }
                    });                     
                    busy.close();

                }

I also tried with sap.ui.core.BusyIndicator.show(), hide(), creating separate BusyDialog.fragment and calling explicitly in controller. But none of the ways worked.

But when i try to debug, then im not getting any issue. BusyIndicator is loading perfectly if im keeping breakpoint.

Can someone help me to load BusyDialog at the before calling POST call and close BusyDialog once the execution of services finished.

Upvotes: 0

Views: 2791

Answers (3)

alexP
alexP

Reputation: 3765

Please use batch requests instead of single requests in loops.

var sError;
var aErrorMessages = [];
var payload = {
  "sectionIndex": 3,
  "ratingType": "overall",
  "userId": "",
  "rating": "76",
  "ratingKey": "wf_sect_3_rating"
};

var busy = new sap.m.BusyDialog();
busy.open();

oModel.setUseBatch(true);
oModel.setDeferredGroups(["myBatchRequest"]);

for (var i = 0; i < 10; i++) { //Loop
  oModel.create("/URL", payload, { //Create request without sending
    groupId: "myBatchRequest",
    changeSetId: "myChangeSet",
    single: false,
    success: function(oData, oResponse) { //Catch error for each request
      if (oData.results[0].status !== "OK") {
        aErrorMessages.push("Error : " + oData.results[0].message); //store error message for each request
      }
    }.bind(this),
    error: function(e) {
      aErrorMessages.push(e);
    }
  });
}

oModel.submitChanges({ //Send all requests at once
  groupId: "myBatchRequest",
  success: function(oResponse) {
    if (aErrorMessages.length > 0) { //Are there any errors...
      for (var i = 0; i < aErrorMessages.length; i++) { 
        sError += aErrorMessages[i]; //...put it in string
      }
      MessageBox.error(sError); //Show all errors
      busy.close(); //Close Busy Dialog
    } else {
      this.getView().getModel("employeesModel").refresh(true);
    }
  }.bind(this),
  error: function(oError) {
    MessageBox.error(oError);
    busy.close(); //Close Busy Dialog
  }
});

Upvotes: 1

pguddi
pguddi

Reputation: 345

For this scenario I would recommend using Promises

var payload = {
  sectionIndex: 3,
  ratingType: "overall",
  userId: "",
  rating: "76",
  ratingKey: "wf_sect_3_rating"
};
//var busy = new sap.m.BusyDialog();
//busy.open();
var aPromises = [];
// Open your busy dialog
for (var i = 0; i < 10; i++) {
  //var busy = new sap.m.BusyDialog();
  //busy.open();

  var that = this;
  var pCall = new Promise(function(resolve, reject) {
    oModel.create("/URL", payload, {
      success: function(oData, oResponse) {
        resolve();
        if (oData.results[0].status === "OK") {
          that
            .getView()
            .getModel("employeesModel")
            .refresh(true);
        } else {
          MessageBox.error("Error : " + oData.results[0].message);
        }
      },
      error: function(e) {
        reject();
        MessageBox.error("Error : " + e);
      }
    });
    aPromises.push(pCall);
  }).bind(this);

  Promise.all(aPromises).then(function() {
    // Happy case
    // Close your busy dialog
  }, function() {
      // At least one of the promises went wrong
  });
  //busy.close();
}

Note that once one of the Promises is rejected, it will go into the second function of Promise.all(), so maybe just use resolve()

Upvotes: 3

DubZ
DubZ

Reputation: 582

You can solves it by using oData model method attachRequestCompleted. An easy way would be.

if(i == 10) {
  oModel.attachRequestCompleted(function(oEvent) {
    busy.close();
  });
}

Of course that's not a perfect solution because it could be, that the 9th request is later finished than your 10th etc.

Normally you need to check every request and if every request is completed successfully, the busy dialog get closed. if one or more of them got an error, you can close if all 10 requests are completed you can close the busy dialog and you show an error message or sth.

so normally on every attachRequestCompleted you need to check your loop counter if it's size is 10 and if yes, you can close the dialog.

Upvotes: 0

Related Questions