TransWikia.com

Trouble Fetching JSON files on server into Javascript Array

Stack Overflow Asked on January 27, 2021

I’m quite new to using Javascript and particularly JSON, and I’ve been struggling to do this:

There is a JSON file on my web server which I am trying to access and parse into a JavaScript object. What I am trying to do is parse that JSON into an array and then further manipulate that array based on other user variables.

This is a sample of what the JSON looks like:

{"log":
[{
"name":"Al",
"entries":[8,12,16,19]},
{"name":"Steve",
"entries":[11,17,22]}]}

What I need to do is retrieve the array for one of the entries and store it in an array as a JavaScript object. What I have tried to do is this:

var entriesLogged;

fetch ('url to the json file').then(function(response){
  return response.json();
}).then(function(data){
  entriesLogged = data.log[0].entries;
});

However, I can’t seem to get this to work and to assign the value to the variable in a way that persists outside of this scope. I have been able to output the value of the array using console.log, but I have not been able to actually work with and manipulate that data like an object. I’d ideally like to parse the JSON file from the server onto a global array.

Most of the tutorials I’ve come across so far have used the JSON file to output console logs or change the contents of html elements, however I need to retrieve the values from the JSON into a global array first.

Am I missing something here? Does anyone have advice on how to do this?

Best wishes,
Dom

3 Answers

There are TONS of "answers" for variations of this question that don't actually solve the problem, they just describe the issue. (tl;dr solution is last block of code)

The issue is that .fetch('URL.json') and .json() are "asynchronous" calls. So the script will start working on that call, then continue on to the rest of the commands in your script while the .fetch() and .json() calls are still being worked on. If you then hit a command BEFORE one of these asynchronous calls is done, the rest of your script will have no data to work with.

There are tons of places to look for fully understanding the ins and outs of how async calls work in JS, for example here: How do I return the response from an asynchronous call?

If you're like me and you just want the code to function synchronously, the quick and dirty solution is to create an async main loop and then to make sure you use the await keyword when calling asynchronous functions that you need to WAIT for the data to be populated on.

Example main loop:

(async () => {
    // put main loop code here
})();

You would then put your code inside that main loop BUT you have to make sure that you're adding the await keyword in front of every asynchronous call you use. in the original example provided, you'll have to declare your .then() functions that need to use await as async as well. This is confusing if you don't fully understand the asynchronous nature of javascript and I'll simplify it later, but I wanted to provide a working version of the original code provided so you can understand what changed:

(async () => {
    var entriesLogged;

    await fetch('url_to_the_file.json')
        .then( async function(response){
            return await response.json();
        })
        .then( function(data){
            entriesLogged = data;
        });
})();

The .then() call is typically used for post-processing so you can do work inside of the asynchronous call... but since in this example we're deliberately making it synchronous, we can avoid all of that and clean up the code by doing individual simple commands:

// Start main loop
(async () => {
    let response = await fetch('url_to_the_file.json');
    let entriesLogged = await response.json();
})();

That should get you what you're looking for and hopefully save anyone like us the heartache of spending hours of time trying track down something that there is a simple solution for.

Also want to give a huge call out to the place I got the solution for this: https://www.sitepoint.com/delay-sleep-pause-wait/

Answered by Rob Traynere on January 27, 2021

What is happening is that the call is async, it means that when you make that call a new thread is created and javascript automatically passes to the next line.

var entriesLogged;
fecth(something).then(function(data){entriesLogged = data[0]}); // this goes to another thread an takes e.g. 5 miliseconds but javascript does not wait for this to complete, it goes to the next line
console.log(entriesLogged); // this is executed before the call is finished

Answered by Raul Mercado on January 27, 2021

Are you trying to manipulate the entriesLogged variable after the fetch promise chain? The fetch is asynchronous so this means that any code after the fetch chain will run before the fetch chain finishes.

var entriesLogged;

fetch('url to the json file').then(function(response){
  return response.json();
}).then(function(data){
  entriesLogged = data.log[0].entries;
});

// Code down here will run before the fetch chain finishes
// So if you're using entriesLogged down here, it will be null

console.log(entriesLogged); // entriesLogged is null

You might want to do something like:

.then(function(data){
  entriesLogged = data.log[0].entries;
  myFunction(entriesLogged);
});

function myFunction(myData) {
  console.log(myData); // can access entriesLogged here
}

Answered by laseq on January 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP