简体   繁体   中英

async/await fetch API call that maintains the order

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': {} } }

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); };

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM