I have arrays like below.
var clients = ['a','b'];
var reports = ['x','y','z'];
var finalData = [];
Now i need looping like this.
for(var i=0;i<reports.length;i++){
var response = {report : reports[i]}
for(var j=0;j<clients;j++){
response.client = clients[i];
$.ajax({
url :url,
success : function(data){
response.data = data;
finalData.push(response);
})
});
}
}
As ajax is asynchronous so it does not work properly. Also I need to wrap this up into react.js componentDidMount function and push the finalData into the state.
I tried $.each
instead of for loop and .bind(this)
to push the finaldata into the state. but i didnt get the correct data. I heard for async calls closure should be used but not getting how will that be implemented here. The output i am looking for is.
finalData = [
{client:a,report:x,data : 'xyz'},
{client:b,report:x,data : 'xyz'},
{client:a,report:y,data : 'xyz'},
{client:b,report:y,data : 'xyz'},
{client:a,report:z,data : 'xyz'},
{client:b,report:z,data : 'xyz'}
]
You have to save the scope(use colsure) for your response variable, try the following:
for(var i=0;i<reports.length;i++){
var response = {report : reports[i]}
for(var j=0;j<clients;j++){
response.client = clients[i];
(function(responce){
$.ajax({
url :url,
success : function(data){
response.data = data;
finalData.push(response);
})
})(responce);
});
}
}
let's explain it more, to simulate ajax will use setTimeout
here in the example:
let's consider this example, its a loop 5 times and after a sec will need to print i
we are expecting to print 0 1 2 3 4 but actually it will print 5 for the 5 times because the for loop end before the 1 sec consume and then when it search for i to print i in this case = 5
for(var i=0;i<5;i++){
setTimeout(function(){
console.log(i);
console.log("....");
}, 1000)
}
and to solve that will need to have a scope to save the value for i so when the timeout finish it can find the correct value for i which is called closure:
for(var i=0;i<5;i++){
(function(i){
setTimeout(function(){
console.log(i);
console.log("....");
}, 1000)
})(i);
}
this code will work as expected will print 0 1 2 3 4 correctly and that is what have done for your example.
and for updating the state you can either update it each time you receive a value as:
var that = this; // to be added in top of the 2 for loops
finalData.push(response);
this.setState({data: finalData})
or you can check if the all reports loaded for all clients and then update the state:
// total can be calculated by num of reports X number of clients
if(finalData.length == total){
this.setState({data: finalData})
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.