Reputation: 301
I am trying to get synchronized flow inside a for loop which each loop having to call a API
.
The flow is summarized as follows:
Demo1() function
containing forloop executes one by one, however in each loop it does a API call.,MainFunction()
retrieves after the for loop has executed and does the final API call.Supporting API calls for the same function is shown in code and seems quite self explanatory
The code structure is as follows:
</script>
...
async MainFunction() {
if (dataPresent) {
let clientFieldDetails = await this.Demo1()
.then(() => {
//This does the final API call based on the results fetched from for loop
this.processFinalAPICall();
})
.catch(err => {
console.log("Something went wrong... ", err);
});
} else {
console.log(
"No data.."
);
}
},
async Demo1() {
//Traversing around each fieldInfo
//this.dataPresent.items.forEach(item => {
//Replacing with normal for loop
for(item of this.dataPresent.items){
if (item.model) {
//Upload item model API Call
this.uploadItem(item.model)
.then(response => {
//PUT API Call
this.putItemModel().then(response => {
var result = response.data;
//Add itemModel fetched from API response
models.push(result);
console.log(result)
});
})
.catch(err => console.log("Axios err: ", err));
} else {
//Inside item price details
console.log("inside item price");
//API call for fetching price info
this.getitemPriceInfo(item.id);
}
});
},
getitemPriceInfo(itemid){
if(itemid){
//API call for fetching price info
this.getPriceinEuro(itemid);
itemsPrice.push(result)
}
else{
this.getPriceWorldWide().then(response => {
if(response.data === "item not created")
//Create new item API call
this.createNewItem(item.id)
else{
var result = response.data;
//Fetched API response for itemsPrice
itemsPrice.push(result);
console.log(result);
//Update item API call
this.updatePriceItem(item.id);
}
});
}
},
//EDIT: Adding API call
async getPriceinEuro(itemId) {
await this.$axios
.get("/auth/getEuroPrice", {
params: {
itemID: itemId
}
})
.then(response => {
console.log(" Resp :" + response.data);
let result = response.data;
//This gives me the price
itemsPrice.push(result)
});
},
processFinalAPICall(){
//get itemsPrice and models price pushed
var apiBodyModel = [];
this.models.forEach(model=>{
var uri = {
url: /modelInfo/+model
}
apiBodyModel.push(uri)
})
var apiBodyPrice = [];
this.itemsPrice.forEach(price=>{
var uri = {
url: /priceInfo/+price
}
apiBodyPrice.push(uri)
})
//Create a post body request from above data and POST
....
}
...
</script>
The code currently loops in for loop and doesnt wait for the API calls to finish. It executes processFinalCall() first and then the API calls. I am not sure about async/await
, if I used it wrong please excuse. How do i get the the forLoop executed first and then the initiating the processFinalAPICall()
from MainFunction?
Please let me know if I am doing it the right way. Thanks :)
I am using Node version 8.11
due to our project dependencies.
EDITED: Added API function Call for reference
Upvotes: 2
Views: 2072
Reputation: 494
I guess its a simple change over from what @marsnebulasoup added in his mockup solution. From your comments I tried to replace upload method
with axios
call. You are missing return
keyword after the function call , i.e,
upload(item) {
console.log("Iten value:"+ item);
return axios.get("https://jsonplaceholder.typicode.com/posts/" +item)
.then(response => {
console.log("Done processing API call (Times:"+ item)
console.log(response.data);
})
.catch(console.log);
A simple code changeover is designed based on previous answer by @marsnebulasoup in Replit:
EDIT: Added correct reference:
Code Reference: https://replit.com/join/comkahdm-gagangowda89
Cheers.
Upvotes: 1
Reputation: 2660
I'm fairly sure that the problem you have lies in your Demo1
function, which, very broadly, looks like this:
async Demo1() {
[ARRAY OF ITEMS].forEach(item => {
this.uploadItem(item)
.then(response => {
// do some stuff
});
.catch(err => /* log errors */);
});
}
You don't await
the upload here, so when you call Demo1()
in MainFunction()
, it'll go through the uploads without waiting for the previous one to finish first. I think the easiest way to get around this would be to use a for-of loop instead, since you pass a function to .forEach
, and that just complicates things.
So instead of [ARRAY OF ITEMS].forEach(item => { ...
, you can do this:
async Demo1() {
for(let item of [ARRAY OF ITEMS]) {
await this.uploadItem(item);
}
}
And your modified Demo1
function would look like this:
async Demo1() {
//Traversing around each fieldInfo
for (let item of this.dataPresent.items) {
if (item.model) {
//Upload item model API Call
await this.uploadItem(item.model)
//PUT API Call
let response = await this.putItemModel();
var result = response.data;
//Add itemModel fetched from API response
models.push(result);
console.log(result)
} else {
//Inside item price details
console.log("inside item price");
//API call for fetching price info
this.getitemPriceInfo(item.id);
}
};
}
Note that I haven't tested this, because I don't have the full code to plug it into, so I can't fully guarantee that it'll work. If it doesn't, let me know, so I can help fix it
Here's a bad mockup of this solution.
Upvotes: 2