Reputation: 1409
I have a javascript function which triggers when a button
is clicked. The function takes a data-attribute
from the button
element, and uses this as a key to find a value from a JSON dataset.
If the JSON data has already been downloaded from the first button click, I don't want to download the dataset again as there is no reason to do so.
I have tried to do this by declaring an empty array. I then find the length of the array, if the length is 0, I get the JSON data and push it to the array. If the array length is more than 0, I know that I can use this data.
I'm not sure why, but every-time I run the function, the data is redownloaded, regardless of the conditional statement.
Here is my code
let arr = [[0,"Bulbasaur"],[1,"Ivysaur"],[2,"Venusaur"],[3,"Charmander"],[4,"Charmeleon"]]
let output = document.getElementById('output')
for (var key in arr) {
let button = document.createElement('button')
button.innerHTML = arr[key][1]
button.addEventListener('click',go)
button.setAttribute('data-key',arr[key][0])
output.append(button)
}
data = []
fetch("https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json")
.then(response => {
return response.json();
})
.then(jsondata => data.push(jsondata))
function go() {
if (data.length > 0) {
fetch()
console.log('This data is new')
}
else {
console.log('This data is not new')
}
let key = this.dataset.key
document.getElementById('img').setAttribute('src',data[0].pokemon[key].img)
}
<img id="img" src=""/>
<div id="output"></div>
Does anyone know how to load the data only when necessary?
Upvotes: 0
Views: 209
Reputation: 34217
You had your conditional backwards so it did an empty fetch, seemed odd. I set this up as an object and set the fetch inside one of the objects function and just called it - this also avoid pollution of the global namespace with a "common" variable name like "data" or "arr" etc.
var myObject = {
arr: [
[0, "Bulbasaur"],
[1, "Ivysaur"],
[2, "Venusaur"],
[3, "Charmander"],
[4, "Charmeleon"]
],
logMessage(message) {
console.log(message);
},
go: function() {
if (myObject.data.length <= 0) {
myObject.goGetem()
myObject.logMessage('This data is new');
} else {
myObject.logMessage('This data is not new');
}
let key = this.dataset.key;
document.getElementById('img').setAttribute('src', myObject.data[0].pokemon[key].img);
},
output: {},
data: [],
goGetem: function() {
myObject.logMessage('retreiving data');
fetch("https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json")
.then(response => {
return response.json();
})
.then(jsondata => myObject.data.push(jsondata))
.then(function() {
myObject.logMessage('We fetched data: ' + !!myObject.data.length);
//use this to see what we got by uncommenting:
//myObject.logMessage(myObject.data);
});
},
setup: function() {
myObject.output = document.getElementById('output');
myObject.goGetem();
for (var key in myObject.arr) {
let button = document.createElement('button');
button.innerHTML = myObject.arr[key][1];
button.addEventListener('click', myObject.go);
button.setAttribute('data-key', myObject.arr[key][0]);
myObject.output.append(button);
};
}
};
myObject.setup();
<img id="img" src="" />
<div id="output"></div>
Upvotes: 1
Reputation: 3714
If needed some code optimization.
Add event listener to parent div instead of adding an event for each new button This will reduce the number of event listeners.
output.addEventListener('click', go);
Use DocumentFragment instead of updating DOM upon each new button creation.
let fragment = new DocumentFragment();
Append newly created button to fragment
fragment.appendChild(button);
Finally, Append created fragment to target element #output
output.appendChild(fragment);
Then how to get dataset key of button in go
function? Simple get target element on which click event was occurred then get its key using dataset.
let key = event.target.dataset.key;
Below code, if data length is 0. execution will wait for API call to finish, Hence await. To use await we need to mark its container function as async
let output = document.getElementById('output');
output.addEventListener('click', go);
let arr = [[0,"Bulbasaur"],[1,"Ivysaur"],[2,"Venusaur"],[3,"Charmander"],[4,"Charmeleon"]]
let fragment = new DocumentFragment();
for (var key in arr) {
let button = document.createElement('button')
button.innerHTML = arr[key][1]
//button.addEventListener('click',go)
button.setAttribute('data-key',arr[key][0]);
fragment.appendChild(button);
}
output.appendChild(fragment);
data = [];
async function go(event){
if(data.length==0) {
await fetch("https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json")
.then(response => response.json())
.then(jsondata => data.push(jsondata));
}
// get dataset of the target element
let key = event.target.dataset.key;
document.getElementById('img').setAttribute('src',data[0].pokemon[key].img)
}
<img id="img" src=""/>
<div id="output"></div>
Upvotes: 1
Reputation: 23500
Try like this:
let arr = [[0,"Bulbasaur"],[1,"Ivysaur"],[2,"Venusaur"],[3,"Charmander"],[4,"Charmeleon"]]
let output = document.querySelector('#output')
for (let key in arr) {
let button = document.createElement('button')
button.innerHTML = arr[key][1]
button.addEventListener('click',go)
button.setAttribute('data-key',arr[key][0])
output.append(button)
}
data = []
async function go() {
if (data.length === 0) {
await fetch("https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json")
.then(response => {
return response.json();
})
.then(jsondata => data.push(jsondata))
console.log('This data is new')
}
else {
console.log('This data is not new')
}
let key = this.dataset.key
document.querySelector('#img').setAttribute('src',data[0].pokemon[key].img)
}
<img id="img" src=""/>
<div id="output"></div>
Upvotes: 1