Home > Mobile >  Load multiple json then execute funtion
Load multiple json then execute funtion

Time:10-20

I have a list of JSON files in a variable and I want to load the content of these files into a single object. The json files have two keys: metadata and outputs.

Once this is done, I want to call a function that generates a list of tables. I am able to do this if I have only one file. The code I use to do so is:

jQuery.getJSON(filePath, function(data) {
    jQuery.each(data, function(key, val){
        if ( key === "outputs"){
            new tableGenerator(val);
        };
    });
});

when I try to get the data from different files I obtain an empty variable. To load different files I use:

var fileList = ["dataFolder/data1.json",
                "dataFolder/data2.json",
                "dataFolder/data3.json"]

var jsonData = [];

jQuery.when(
    fileList.forEach( file => {
        jQuery.getJSON(file, function(data) {
            jQuery.each(data, function(key, val){
                if ( key === "outputs"){
                    jsonData = jsonData.concat(val);
                }; 
            });
        });
    })
).then(function(){

    console.log(jsonData);

    new tableGenerator(jsonData);
})

I don't work normally in javascript and I don't understand why normally the tableGenerator function is executed before the jsonData handler is filled.

Any comment in the code is welcome (style, deprecated...) as I am not a javascript developer and probably a lot of things will be done in an uncommon way.

CodePudding user response:

When expects deferreds as arguments, you are giving it deferreds. You would need to return the deferred the getJSON call returns and set them to when

var fileList = [
  "https://jsonplaceholder.typicode.com/todos/1",
  "https://jsonplaceholder.typicode.com/todos/2",
  "https://jsonplaceholder.typicode.com/todos/3"
]

const calls = fileList.map(path => $.getJSON(path))

$.when(...calls).then((...responses) => {
  const yourData = responses.map(([json]) => json);
  console.log(yourData);
  // call table code
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

without jQuery

var fileList = [
  "https://jsonplaceholder.typicode.com/todos/1",
  "https://jsonplaceholder.typicode.com/todos/2",
  "https://jsonplaceholder.typicode.com/todos/3"
]

const calls = fileList.map(path => fetch(path).then(response => response.json()))

Promise.all(calls).then(yourData => {
  console.log(yourData);
  // call table code
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

CodePudding user response:

The get requests for json files are async. Meaning, you need to correctly await for it to happen.

I would suggest using async/await approach with vanilia JS, without jQuery (aka we live in 2022)

const fileList = ["dataFolder/data1.json", "dataFolder/data2.json", "dataFolder/data3.json"]


async function getData(url) {
    const request = await fetch(url)
    const response = await request.json()
    return response
}

async function generateTables(list){
  let tablesData = [];
  for (const url of list) {
    const data = await getData(url)
    tablesData.push(...data?.outputs) //get only "outputs"
  }
  return [...tablesData]
}

generateTables(fileList).then(result => {
  console.log(result);
  new tableGenerator(result);
})

CodePudding user response:

It's an asynchronous issue. It's a typical behavior of JavaScript, you declare a function that will be launched when the data will be ready. And after declaration, JavaScript run the next statements.

See How to make the getJSON wait before running the rest of the code? to transform your code in a more classic synchronous mode.

await keyword was introudced with ECMAScript 2017, it permits to have code less JavaScrip specific.

  • Related