Using data with fetch

Hello everyone,
I’m learning with Riot API data.
My problem is I can not transfer data I get from Fetch then store the data in a variable outside of fetch.

	fetch("./11.7.1/data/en_US/champion.json")
	.then(resonse => resonse.json())
	.then(returnedData => {
		const arr = Object.values(returnedData.data);
		//I can't transfer arr's data out of fetch body, so I have to call this function in here, which is quite inconvenient
		showImg(arr);
	})

So what I want kind of looks like this:

	const outerArr = [];
	fetch("./11.7.1/data/en_US/champion.json")
	.then(response => response.json())
	.then(returnedData => {
        //It's an object so I need to convert it to array.
		const innerArr = Object.values(returnedData.data);
        //try to get data to the outside variable
		outerArr.push(...innerArr);
	})
    showImg(outerArr);

but it doesn’t work.
I can do console.log(outerArr), it will log an array that contains everything to the console, but then when I try to loop through it, it prints out “undefined”.

     fetch(url)
        .then(do something)
        .then(do something)
    //this returns an array contains the data I want
    showImg(outerArr);
    //this returns "undefined"
   showImg(outer[0]);

Can anyone explain this?
Thank you!

Fetch is asynchronous. You can’t assign data recieved in async outside of asynchronous scope. So you need to perform all actions you need inside of .then()

const outerArr = [];
	fetch("./11.7.1/data/en_US/champion.json")
	.then(response => response.json())
	.then(returnedData => {
      
		const innerArr = Object.values(returnedData.data);
        //try to get data to the outside variable - THIS WON'T WORK
		outerArr.push(...innerArr);
          //you should do all you need here, inside of .then
	})
    showImg(outerArr);

There is very good detailed reply here - javascript - Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference - Stack Overflow

I would suggest you put the fetch inside a function and have the function return the data (or a Promise).

thanks, @VasV !
What you said was what I thought too. But a guy in this video makes me a bit confused about that:

He fetches data from json file, then push(data) in an array which’s outside of fetch scope, then uses the array in other functions(also outside of fetch scope).

hi @lasjorg,
That’s a good idea! I will try that. Thank you for you suggestion!

The way he writes the code in the video can actually fail. Either if the user types before the fetch is done (you can wrap the fetch in a setTimeout to simulate it) and also because there is no error handling at all if the fetch fails.

However, because the data starts out as an empty array you will not get an error. Not throwing an error is definitely better from a user’s point of view, but it can make the code harder to debug because you do not get an error (everything works, the code is just running against an empty array).

Example of order:
const outerArr = [];
fetch("https://ddragon.leagueoflegends.com/cdn/11.8.1/data/en_US/champion.json")
  .then((response) => response.json())
  .then((returnedData) => {
    //It's an object so I need to convert it to array.
    const innerArr = Object.values(returnedData.data);
    //try to get data to the outside variable
    outerArr.push(...innerArr);
    console.log("Log inside fetch");
    console.log(Array.isArray(outerArr));
    console.log(outerArr[0]);
  });

console.log("Log outside fetch");

// Log outside fetch

// Log inside fetch

// true

// {...} some object
2 Likes

hmm, I’m thinking about should I complete his 30 days tutorial or just forget it.
Thank you, once again, @lasjorg!
Btw, I have a question about creating a web page dynamically.
I mean, on my home page, there are 3 buttons.

<a href="./page1">button 1</a>
<a href="./page2">button 2</a>
<a href="./page3">button 3</a>

When users click on one of these buttons, they will be redirected to the respective web page (page1.com || page2.com || page3.com) which doesn’t exist yet.
Is there any way to do that? Create a webpage at the moment users click on a link?
I believe that we can do it, but I don’t know how.

Wes is a good teacher. You should totally do JavaScript30 it’s a great learning resource.

With beginner courses, it’s important not to get bogged down in all the little details. Just like how the JS is written in the HTML file for convenience. That isn’t something you would normally do very often.

What you describe sounds more like a single page application (SPA). In which case, you do not actually navigate to a new page (as in a file on disk) but just update the content of a single page. You can do something simple like have an event listener on the nav link and update the page with the new content when the user clicks it. Or you can implement a router, or use a library (js routing vanilla).

I will continue the tutorial. Thank you!
@lasjorg, I have a few more questions, I know it’s not related to the topic title anymore but I don’t want to create another topic(I don’t want to flood this forum with a bunch of small questions ).
What do you think about for loop performance? I mean between for loop, map, or any other looping method.
Is for loop faster than other methods if I just want to get data from an array, create HTML elements with teamplate string and put it on a webpage like this:

outputVariable =`
		<span>
			<img loading="lazy" class="container__img" src="./img/champion/loading/${arrayIndex.id}_0.jpg" alt="${arrayIndex.id}">
		</span>
		<span class="container__name absolute block uppercase">${arrayIndex.name}</span>`

I like to use the map method, it looks more modern, imo.

I appreciate that you want to be as efficient as possible with your questions but it’s better to create posts around separate issues as you’ll get more eye balls that might have a detailed answer for you.

@DanStockham,
I will do that.
Thank you!

I wouldn’t worry about the performance of map or forEach it’s fairly unlikely they will be your main bottlenecks. If you see performance issues and you can confirm it is the way data is being looped then sure look into ways of optimizing it.

Until then always go for code legibility and declarative code. Using forEach is much cleaner for looping data used for DOM insertion.

yes, I’m having a performance issue when I try to reset typeahead input field, so that I think my problem is the way I apply array methods.
I really like using forEach, it looks very clean, and also very clean behind the scene.
Thank you for your suggestion, @lasjorg !

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.