Reputation: 1
I want to make an async fetch call with await operator. A forEach method iterates over an array of API endpoints, then inserts some values into a local object. See below.
It works great, except - sometimes the values entered into dataModel[index].retailers[i+1] does not align with the index. For example, products for api object 2 will be inserted into local object 4.
I think this has something to do with the asynchronous nature of the request, I thought await might resolve it but it hasn't. Can anyone show me the way?
var api_obj;
// Defining async function
async function getapi(url, index) { // Storing response
var response = await fetch(url)
.then(res => res.json())
.then(data => api_obj = data)
.then(function() {
//iterate over the API object and store required values
//in our local dataModel object
Object.keys(api_obj[0].RetailerProducts).forEach(function(i) {
var i = parseInt(i, 10)
dataModel[index].retailers[i + 1] = {
retailer: api_obj[0].RetailerProducts[i].RetailerName,
url: api_obj[0].RetailerProducts[i].ClickThruUrl,
price: api_obj[0].RetailerProducts[i].Price.toFixed(2),
logo: api_obj[0].RetailerProducts[i].RetailerLogoUrl,
name: api_obj[0].RetailerProducts[i].RetailerProductName
}
})
});
}
//iterate over dataModel and call each API endpoint
Object.keys(dataModel).forEach(function(i) {
// Calling that async function
getapi(dataModel[i].apiEndpoint, i);
})
Here is what dataModel looks like:
var dataModel = {
'1': {
'retailers': {}
},
'2': {
'retailers': {}
},
'3': {
'retailers': {}
}
}
Upvotes: 0
Views: 745
Reputation: 1
I figured out how to solve the ordering issue, here was the solution, basically utilising another .then
method that calls the next function and a counter sitting in global scope:
var apiCounter = 1;
let csApiCall = () => {
var api_obj;
// Defining async function
async function getapi(url, index) { // Storing response
var response = await fetch(url)
.then(res => res.json())
.then(data => api_obj = data)
.then(function() {
//iterate over the object and store required values
//in our dataModel object
Object.keys(api_obj[0].RetailerProducts).forEach(function(k) {
var k = parseInt(k, 10)
dataModel[index].retailers[k + 1] = {
retailer: api_obj[0].RetailerProducts[k].RetailerName,
url: api_obj[0].RetailerProducts[k].ClickThruUrl,
price: api_obj[0].RetailerProducts[k].Price.toFixed(2),
logo: api_obj[0].RetailerProducts[k].RetailerLogoUrl,
name: api_obj[0].RetailerProducts[k].RetailerProductName
}
})
})
.then(function() {
if (apiCounter < Object.keys(dataModel).length) {
apiCounter++;
getapi(dataModel[apiCounter].apiEndpoint, apiCounter);
}
});
}
getapi(dataModel[apiCounter].apiEndpoint, apiCounter);
};
Upvotes: 0