Technical Articles
Multiple asynchronous OData/Ajax calls , in one response !!
What is it all about
I have been seeing many queries in SCN , Stackoverflow and other forums about parallelizing multiple ajax/odata calls and get the response of the calls at once after completing all the request in the queue .
In this blog I discuss about the way I handle such scenarios in my Nodejs projects and UI5 developments.
Before you read further
I use Promises to achieve this scenario . Read about Promises here first.
Scenario
I developed an Odata service, having an entity set “DelaySet”. This entity set has one key , delay , accepts an integer parameter and responds to the call only after the delay
/DelaySet(3) => responds after 3 seconds.
In my application , I am making 5 asynchronous calls with various delays ( say 1, 2 , 3 , 4 & 5 seconds each ) .
var call_1 = "/DelaySet(1)" ;//1 second delay
var call_2 = "/DelaySet(2)" ;//2 second delay
var call_3 = "/DelaySet(3)" ;//3 second delay
var call_4 = "/DelaySet(4)" ;//4 second delay
var call_5 = "/DelaySet(5)" ;//5 second delay
var success = (data)=>{
console.log(data.status);
};
this.oModel.read(call_1,{
success : success
});
this.oModel.read(call_4,{
success : success
});
this.oModel.read(call_3,{
success : success
});
this.oModel.read(call_5,{
success : success
});
this.oModel.read(call_2,{
success : success
});
If you see, these calls will be triggered at once ( in the network tab )
Delayed Calls – I increased the delay to take screenshot
Console
And the response was like this . Now , we want to get the response of all these calls upon completing all the calls.
Write Promises
Lets wrap each of these requests in Promises. Instantiating Promise instances , the OData calls in the constructor function body starts.
//Promise Syntac
var oPromise = new Promise((resolve,reject)=>{
//code we would like to execute
resolve(<data>) ; // when the execution of code completes succesfully
reject(<err>) ; //when it fails
});
Lets wrap one of our calls in a Promise
let p1 = new Promise((resolve,reject)=>{
this.oModel.read(call_3,{
success : (data)=>{
resolve(data);
} ,
error : (err)=>{
reject(err);
}
});
});
If you are not familiar with the ()=>{} syntax , please check Arrow functions this is really good and helpful
The above piece of code executes the promise and after completing the OData execution , it resolves the response data ( we don’t need a “then” chain as we don’t need the data here )
Like this , Defined all the OData calls in promises
let p1 = new Promise((resolve,reject)=>{
this.oModel.read(call_3,{
success : (data)=>{
resolve(data);
} ,
error : (err)=>{
reject(err);
}
});
});
let p2 = new Promise((resolve,reject)=>{
this.oModel.read(call_2,{
success : (data)=>{
resolve(data);
}
});
});
let p3 = new Promise((resolve,reject)=>{
this.oModel.read(call_5,{
success : (data)=>{
resolve(data);
}
});
});
let p4 = new Promise((resolve,reject)=>{
this.oModel.read(call_4,{
success : (data)=>{
resolve(data);
}
});
});
let p5 = new Promise((resolve,reject)=>{
this.oModel.read(call_1,{
success : (data)=>{
resolve(data);
}
});
});
We will see all the OData calls executing in parallel ( like before ) . To capture the results of all the resolved promises , lets pass “Promise.all” method
let finalPromise = Promise.all([p1,p2,p3,p4,p5]).then((dataFromAll)=>{
console.log(dataFromAll);
}).catch((err)=>{ console.log(err) });
Here , after resolving all the passed promise instances , the resolved responses shall be passed as an array .
sequence of objects in the array is as the sequence of promise instance we pass
Note – There are plenty other possible methods to achieve this . But I love coding JS with promises , which gives better control over asynchronous code blocks .
BR – Sreehari
promises ftw!
but don't forget to catch potential errors:
Promise.all(promises).catch( (err) => ... )
also check out Promise.allSettled()
and Promise.race() for the fun 🙂
Never used race() before but it looks really “promising” 😀
Nice example Sreehari V Pillai , working with js will be too boring without promises and now I am loving async/await in nodejs, it's double the fun 🙂