Skip to Content

Introduction

This blog post describes how to call multiple OData requests in parallel and wait all them to finish so that when we have all the responses and after that do something else.



Use case

Imagine that you have two services, first for data and second for authorizations, and you have to activate a button only if first service gives you certain data and second service gives you correct auths. You have to do following two steps:

  1. Request data to a OData service 1
  2. Request data to OData service 2 to check authorizations

But only If 1 and 2 are done and data is retrieved then you have to activate a button.

For that you can use jQuery deferred objects and Promises.

Check following liks for help if you are not familiar with that concepts.

https://api.jquery.com/jquery.deferred/

https://api.jquery.com/jquery.when/

Some examples

https://learn.jquery.com/code-organization/deferreds/examples/

Let’s start with SAPUI5

So we will create one Deferred object for each condition we want to wait and resolve the object when required.

In following example with jQuery.Deferred() we create the object. After that we can create an ODataModel and attach to the metadataLoaded event. Finally when metadata is loaded the Deferred object will be resolved.


            this.oModel2DataDeferred = jQuery.Deferred();
  
  
            var sURI2 = "https://cors-anywhere.herokuapp.com/services.odata.org/V3/OData/OData.svc/";
            var oModel2 = new sap.ui.model.odata.v2.ODataModel(sURI2,oConfig);
  
  
            oModel2.attachEventOnce("metadataLoaded", function() {
                console.log("oModel2: Metadata loaded OK");
                this.oModel2DataDeferred.resolve();
            }, this);
  
  
            var finishWait = function(){
                console.log("this is the end");
            }




We can increase the complexity. We will call another service and another Deferred object but now Deferred object will be resolved when we have a response for a requested data. So if we read the Employees and request was ok, success function will be read and Deferred object is resolved.


            this.oModelDataDeferred = jQuery.Deferred();
                     
 
            var sURI = "https://cors-anywhere.herokuapp.com/services.odata.org/Northwind/Northwind.svc/";
            var oModel = new sap.ui.model.odata.v2.ODataModel(sURI,oConfig);
  
          oModel.attachEventOnce("metadataLoaded", function() {
                console.log("oModel: Metadata loaded OK");
        
            }, this);
  
            
            oModel.read("/Employees", {
  success: jQuery.proxy(fSuccess, this),
                error: jQuery.proxy(fError, this)
  });
            function fSuccess(oEvent){
             console.log("oModel: Employees read successfully!");
             this.oModelDataDeferred.resolve();
            };
            function fError(oEvent){
             console.log("oModel: An error occured while reading Employees!");
            };




How do we wait both Deferred objects to be resolved? Using jQuery.when that returns a Promise that will be resolved as soon as all Deferred objects passed as parameters are resolved.

In our example function finishWait will only be called if both Deferred ( oModelDataDeferred & oModel2DataDeferred ) are resolved, that also means that finishWait is called if:

  1. Employees for service ( http://services.odata.org/V4/Northwind/Northwind.svc/ ) are read
  2. Metadata for service ( http://services.odata.org/V3/OData/OData.svc/ ) is ready

              var finishWait = function(){
                   console.log("this is the end");
             }
            jQuery.when(this.oModelDataDeferred,
                        this.oModel2DataDeferred )
            .done( jQuery.proxy(finishWait,this) );


jsbin example

If you check the example you will see the following messages in the console but the order of appearence of messages 1 2 & 3 is never known. Message 4 will be always the last message for sure.

  1. “oModel2: Metadata loaded OK”
  2. “oModel: Metadata loaded OK”
  3. “oModel: Employees read successfully!”
  4. “this is the end”

Edited on 15/06/2016:

After reading the comments of Buzek Volker  and Maksim Rashchynski I decided to create another example implementing the Promise.all and using the metadataLoaded() method.

JS Bin – example 2

I hope that update helps

Conclusion

With that we have parallel batch requests with SAPUI5 and we have a way to wait all requests using jQuery.

I hope this blog helps someone with same requirements and if you have any doubts or recomendations do not hesitate to contact me

Thanks a lot!

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Maksim Rashchynski

    from 1.30 there is metadataLoaded method which returns promise

    https://sapui5.netweaver.ondemand.com/sdk/#docs/api/symbols/sap.ui.model.odata.v2.ODataModel.html#metadataLoaded

    which makes

    1.    oModel2.attachEventOnce(“metadataLoaded”, function() { 
    2.                 console.log(“oModel2: Metadata loaded OK”); 
    3.                 this.oModel2DataDeferred.resolve(); 
    4.             }, this); 


    redundant

    (0) 
    1. Jose Muñoz Herrera Post author

      Hi Maksim,

      Thanks for the info, I’ll take into account for the next upgrade as I’m still working with 1.28 as it is the current long term support SAPUI5 libraries.

      Thanks a lot

      (0) 
  2. Volker Buzek

    Hi Jose,

    if you use Promise.all() instead of chaining jQuery.Deferred’s, then you get the best of all worlds:

    – Promises executing in parallel

    – Promise.all() only resolves after its last Promise has resolved

    – Promise.all() gives you access to the results/resolves of all contained Promises

    Pseudo-Code:

    Promise.all( [ oModel.loadData(), oModel1.loadData() ] )

         .then( console.log(resulsts) );

    – V.

    (1) 

Leave a Reply