Joe Olsen
Joe Olsen

Reputation: 41

JavaScript fetch to variable issues

Mediocre JavaScript developer here and need some help..

I want to make a GET call to a URL several times in a for loop.

I am trying to use fetch, but because of the promise/timing situation, I can't figure out how to make it work.

Below is the code and it's entirely possible that the fetch approach doesn't make sense for what I am trying to do. Would appreciate your help either helping me with code or telling me I am idiot and advising an alternative :)

var fromAmt = 100;
var fromOOP = 50;
var fromGM = 50;
var fromCur = "USD"
var toCur = ["USD","EUR","INR","GBP","SGD"];

var adjAmt = [];

async function getConversionAsync(fcur,tcur,amt) 
{
  let response = await fetch('https://data.fixer.io/api/convert?access_key=xyxyxyxyxyxyxy&from=' + fcur + '&to=' + tcur + '&amount=' + amt);
  let data = await response.json()
  return data;
}

for (i = 0; i < toCur.length; i++) {

getConversionAsync(fromCur,toCur[0].toString(),fromAmt)
  .then(data => display(data));

}


function display(thing){
adjAmt.push(thing.result);
}

document.getElementById("something").innerHTML = adjAmt[0].toString();

Upvotes: 0

Views: 282

Answers (2)

Jean-Baptiste Martin
Jean-Baptiste Martin

Reputation: 1449

In your example, document.getElementById("something").innerHTML = adjAmt[0].toString(); is executed before anything is pushed to adjAmt. You need to wait for the loop calls to finish before displaying a result, and for this you could wrap everything inside an async function.

const fromAmt = 100;
const fromOOP = 50;
const fromGM = 50;
const fromCur = 'USD';
const toCur = ['USD', 'EUR', 'INR', 'GBP', 'SGD'];

const adjAmt = [];

const getConversionAsync = async (fcur, tcur, amt) => {
    const response = await fetch(`https://data.fixer.io/api/convert?access_key=xyxyxyxyxyxyxy&from=${fcur}&to=${tcur}&amount=${amt}`);
    return response.json();
}

function display(thing) {
    adjAmt.push(thing.result);
}

(async () => {
    for (i = 0; i < toCur.length; i += 1) {
        const data = await getConversionAsync(fromCur, toCur[0], fromAmt);
        display(data);
    }
    document.getElementById('something').innerHTML = adjAmt[0].toString();
})();

Upvotes: 1

Phix
Phix

Reputation: 9900

Some small changes to make it work without the API call, but you'll want to access the correct index in your loop. I don't know what the exact output you're wanting here but in this case I just joined all the values in the array.

Additionally, the setting of innerHTML needs to be done once all the values are retrieved from the API, so I would even suggest doing that when the loop terminates, or some other "done" type event.

Additionally, you can use Promise.all instead of a loop, which is what I would go with personally.

var fromAmt = 100;
var fromOOP = 50;
var fromGM = 50;
var fromCur = "USD"
var toCur = ["USD", "EUR", "INR", "GBP", "SGD"];

var adjAmt = [];

async function getConversionAsync(fcur, tcur, amt) {
  let response = await sampleRequest()
  /* let data = await response.json() */
  return response;
}

for (i = 0; i < toCur.length; i++) {
  const data = getConversionAsync(fromCur, toCur[i].toString(), fromAmt).then(data => {
	  display(data)
  })
}


function display(thing) {
  adjAmt.push(thing);
  document.getElementById("something").innerHTML = adjAmt.join(', ')
}

function sampleRequest() {
	return new Promise((resolve, reject) => {
  	resolve(Math.round(Math.random() * 1000))
  })
}
<div id="something"></div>

Upvotes: 0

Related Questions