Create a Variable for an Imported JSON File

Hey folks, I’m building out some basic vanilla js projects (randomized background color changer) and I figured out the code to accomplish that with an array variable INSIDE of my javascript file.

I wanted to take it a step further and implement this from a much larger data set. I found a JSON file online with 1000+ colors. This is my first time using a JSON file. I have it uploaded in the same directory as my other index.html, css, and js files. The data in the file looks like this:

[
    {
      "name": "Absolute Zero",
      "hex": "#0048BA"
    },
    {
      "name": "Acid Green",
      "hex": "#B0BF1A"
    },
...

I then found a tutorial about importing JSON files into a javascript file. This is the code I found:

fetch ("./colors.json")
    .then(function(resp) {
        return resp.json();
    })
    .then(function(colorsArr) {
        console.log(colorsArr);
    });

While this does successfully log the array…I can’t figure out how to get this content into a GLOBAL variable so I can access its data in functions and event listeners.

I tried the following:

let globalColorsArr = fetch ("./colors.json")
    .then(function(resp) {
        return resp.json();
    })
    .then(function(colorsArr) {
        console.log(colorsArr);
    });
console.log(globalColorsArr);

But it says that it’s a Promise Pending…I know promises are a more advanced subject within JS, and I do intend on learning about that, but for now, I would just like to be able to access the colors array. Does anyone see a quick solution to this?

This is something that is best explained through a lesson (example the one here in FCC), and then learned through practice. Asynchronous programming and promises can be a lot to process.

But to solve your current issue, you merely have to understand what is happening.
fetch is a function call that returns a promise, which can be further processed by then() or catch() into another promise, on and on in a process called promise chaining until your desired result.

Now to look at this block of code, you are assigning to globalColorsArr the value of running fetch(url).then(func).then(func), which would be a promise, not the array you want.

In the fetch, you get a file from the url. In the first then, you tell the browser how to interpret it, (it is a json). Therefore when the first then passes a variable to the second then, and you call it colorsArr, that is already what you want. write globalColorsArr=colorsArr instead of your console.log and you will have the array saved.

You should also call fetch alone without assigning it to anything if you won’t do further async programming with it.

Here is a good resource on promises. Promises, async/await

Hey, thanks for taking the time and effort to respond with such depth. I appreciate it. I will read up on the documentation you linked out.

var globalColorsArr = 
fetch ("./colors.json")
    .then(function(resp) {
        return resp.json();
    })
    .then(function(colorsArr) {
        globalColorsArr = colorsArr;
    });
console.log(globalColorsArr.length); // prints undefined

I tried the code you suggested but it’s rending the output as undefined. Any thoughts as to why that is?

Hi, you will need to chain another then to see the correct updated globalColorsArr. The reason is again the asynchronous aspect of the code. Once JS sees fetch, it jumps ahead to synchronous code it can do before going back to the async fetch. So in the console.log nothing has been assigned to globalColorsArr yet.

Instead:

var globalColorsArr;

fetch ("./colors.json")
    .then(response=>resp.json())
    .then(colorsArr=> globalColorsArr = colorsArr)
    .then(()=>{
             //do work with globalColorsArr here 
             console.log(globalColorsArr);
    });

Or just log globalColorsArr after the assignment inside the second then.

let objectCount;

fetch('./jsonData.json')
  .then((data) => data.json())
  .then((json) => {
    objectCount = json.length;
    console.log(objectCount);
  });

If you want to write more synchronous-looking asynchronous code I would look at using async/await.