Tengo una función javascript que se activa cuando se hace clic en un button . La función toma un data-attribute del elemento de button y lo usa como clave para encontrar un valor de un conjunto de datos JSON.
Si los datos JSON ya se han descargado desde el primer clic del botón, no quiero volver a descargar el conjunto de datos porque no hay razón para hacerlo.
He intentado hacer esto declarando una matriz vacía. Luego encuentro la longitud de la matriz, si la longitud es 0, obtengo los datos JSON y los inserto en la matriz. Si la longitud de la matriz es mayor que 0, sé que puedo usar estos datos.
No estoy seguro de por qué, pero cada vez que ejecuto la función, los datos se vuelven a descargar, independientemente de la declaración condicional.
Aquí está mi código
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>¿Alguien sabe cómo cargar los datos solo cuando es necesario?
Prueba así:
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>Si es necesario alguna optimización de código.
Agregue un detector de eventos al div principal en lugar de agregar un evento para cada botón nuevo. Esto reducirá la cantidad de detectores de eventos.
output.addEventListener('click', go);Use DocumentFragment en lugar de actualizar DOM cada vez que se crea un nuevo botón.
let fragment = new DocumentFragment();Agregar botón recién creado para fragmentar
fragment.appendChild(button); Finalmente, agregue el fragmento creado al elemento de destino #output
output.appendChild(fragment); Entonces, ¿cómo obtener la clave del conjunto de datos del botón en la función go ? Simplemente obtenga el elemento de destino en el que se produjo el evento de clic y luego obtenga su clave usando el conjunto de datos.
let key = event.target.dataset.key;Debajo del código, si la longitud de los datos es 0, la ejecución esperará a que finalice la llamada a la API, por lo tanto, espera . Para usar await, debemos marcar su función de contenedor como asíncrona
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>Tenías tu condicional al revés, por lo que hizo una búsqueda vacía, parecía extraño. Configuré esto como un objeto y configuré la búsqueda dentro de una de las funciones de objetos y simplemente la llamé; esto también evita la contaminación del espacio de nombres global con un nombre de variable "común" como "datos" o "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>