Home > Mobile >  How can I store a JSON file in Javascript to use continuously?
How can I store a JSON file in Javascript to use continuously?

Time:11-23

I'm making a website and on one of my pages I have this button that when clicked, should take a haiku from a JSON file that contains over 5000 and display it to the user. Currently I do this the following way.

<script>
    const haikuUrl = 'http://mywebsite/haikus.json';
    async function getHaiku() {
        const num = Math.floor(Math.random() * 5145);
        const response = await fetch(haikuUrl);
        const data = await response.json();
        const {line1, line2, line3} = data[num];
        document.getElementById('line1').textContent = line1;
        document.getElementById('line2').textContent = line2;
        document.getElementById('line3').textContent = line3;
    }
    document.getElementById('haikuButton').addEventListener('click', () => {
         getHaiku();
    });
</script>

I'm pretty much new to JS, and after looking around and watching some videos this was the only way I could get this to work but I'm pretty much sure there has to be a better way to do this. Right now, I'm having to load the whole file every time just to get 1 random object from the JSON. What I'd like to have is a constant or a variable that just sits there waiting for the user to ask for a random one. Something like this:

<script>
    const data= [{},{},{}...{}]; //an array of all the haikus loaded once at the beginning
    function getHaiku() {
        const num = Math.floor(Math.random() * 5145);
        const {line1, line2, line3} = data[num];
        document.getElementById('line1').textContent = line1;
        document.getElementById('line2').textContent = line2;
        document.getElementById('line3').textContent = line3;
    }
    document.getElementById('haikuButton').addEventListener('click', () => {
         getHaiku();
    });
</script>

So pretty much the same just without the having to fetch the whole data every time.

I guess one option could be to hardcode the whole dataset into the js file into a variable, but something tells me there's got to be a better way.

CodePudding user response:

I would first fetch the data, then choose a random haiku by using the randomly generated number as an index of the data array. Something like below: I have not tested the code below so I am not sure if it works, but hopefully this nudges you in the right direction.

let data;
let button = document.getElementById('haikuButton');
let randomHaiku = '';

// Fetch data
async function getHaikus(){
   const response = await fetch('http://mywebsite/haikus.json')
   data = await response.json();
}

// Generate random number
function generateRandomNumber(array){
  return Math.floor(Math.random() * array.length)
}

// get random haiku
button.addEventListener('click', ()=>{
   let index = generateRandomNumber(data)
   randomHaiku = data[index]
   
   console.log(randomHaiku);

}, false)


getHaikus();

CodePudding user response:

If I understand correctly your question, one optimization you can do is as follows:

const haikuUrl = 'http://mywebsite/haikus.json';
let haikus = null;
async function getHaiku() {
    const num = Math.floor(Math.random() * 5145);
    if (!haikus) {
        const response = await fetch(haikuUrl);
        haikus = await response.json();
    }
    const {line1, line2, line3} = haikus[num];
    [...]
} 

So it would download the file the first time the user clicks on the button, but not download it again if the user clicks on the button again (unless they close the webpage in between). You should also definitely use the length of the array instead of hardcoding 5145, as mentioned in other answers.

It is also certainly possible to embed the data directly in the JS file, but it won't make much difference, it will just make the JS file (which must be downloaded as well) much bigger. So it wouldn't solve the problem of needing to download all the haikus when you need just one.

Making it so that it really only downloads one haiku is a bit more complicated. You could have a backend that the frontend requests a single haiku to (but that probably increases complexity significantly if you currently don't have a backend). You could also store all haikus in separate files with predictable names (for instance haikus/42.txt) and fetch only a single such file.

  • Related