Categoría: JavaScript
Truco para eliminar listeners de funciones flechas
Básicamente cambiar el prototype para que internamente guarde un Symbol (id única) y nos permita eliminarlas:
(function() { let target = EventTarget.prototype; let functionName = 'addEventListener'; let func = target[functionName]; let symbolHidden = Symbol('hidden'); function hidden(instance) { if(instance[symbolHidden] === undefined) { let area = {}; instance[symbolHidden] = area; return area; } return instance[symbolHidden]; } function listenersFrom(instance) { let area = hidden(instance); if(!area.listeners) { area.listeners = []; } return area.listeners; } target[functionName] = function(type, listener) { let listeners = listenersFrom(this); listeners.push({ type, listener }); func.apply(this, [type, listener]); }; target['removeEventListeners'] = function(targetType) { let self = this; let listeners = listenersFrom(this); let removed = []; listeners.forEach(item => { let type = item.type; let listener = item.listener; if(type == targetType) { self.removeEventListener(type, listener); } }); }; })(); document.addEventListener("DOMContentLoaded", event => { console.log('event 1'); }); document.addEventListener("DOMContentLoaded", event => { console.log('event 2'); }); document.addEventListener("click", event => { console.log('click event'); }); document.dispatchEvent(new Event('DOMContentLoaded')); document.removeEventListeners('DOMContentLoaded'); document.dispatchEvent(new Event('DOMContentLoaded'));
Enlaces JS
React, the beginning
Para empezar:
https://www.w3schools.com/react/default.asp
https://ibaslogic.com/react-tutorial-for-beginners/
https://leanpub.com/reactjsforthevisuallearner/read#leanpub-auto-chapter-1–what-is-this-all-about
Para seguir:
https://fullstackopen.com/es/about
Hooks:
https://css-tricks.com/react-hooks-the-deep-cuts/
https://www.freecodecamp.org/news/react-hooks-fundamentals/
Ebook:
Ejercicio typicode
Con la web https://jsonplaceholder.typicode.com/guide/ vamos a mostrar un selector de usuarios (con sus nombres) cuando seleccionemos uno nos mostrarán todos los ‘todos’ que tiene, cada uno tendrá a su lado un botón de editar y otro de borrar. También tendremos un botón de añadir un ‘todo’ a ese usuario.
Await vs then
async function showAvatar() { let img; // leer nuestro JSON fetch('https://es.javascript.info/article/promise-chaining/user.json') .then((response) => response.json()) .then(res => { fetch(`https://api.github.com/users/${res.name}`) .then((response) => response.json()) .then(result => { img=document.createElement('img'); img.src=result.avatar_url; img.className="promise-avatar-example"; document.body.append(img); }); }) // espera 3 segundos await new Promise((resolve, reject) => setTimeout(resolve, 3000)); img.remove(); //return githubUser; }
async function showAvatar() { // leer nuestro JSON let response = await fetch('/article/promise-chaining/user.json'); let user = await response.json(); // leer usuario github let githubResponse = await fetch(`https://api.github.com/users/${user.name}`); let githubUser = await githubResponse.json(); // muestra el avatar let img = document.createElement('img'); img.src = githubUser.avatar_url; img.className = "promise-avatar-example"; document.body.append(img); // espera 3 segundos await new Promise((resolve, reject) => setTimeout(resolve, 3000)); img.remove(); return githubUser; }
Ejercicio fetch
En esta api:
https://rickandmortyapi.com/documentation
Nos dan información acerca de los capítulos de la estupenda serie Rick y Morty.
Vamos a crear una página en la que tengamos un selector con todas las especies que aparecen en la serie y todas las localizaciones y cuando seleccionemos una u otra (o las dos) nos aparezcan las imágenes de los personajes que son de esa especie o de esa localización (o las dos).
Ejemplo fetch cartas
<div id="contenedor" class="container"> <button id="empezar" class="btn btn-success">Empezar</button> <p id="mensaje"></p> <button id="carta" class="btn btn-success">Sacar una carta</button> <button id="carta5" class="btn btn-success">Sacar cinco cartas</button> <div id="cartas"></div> </div> <script src="js/cartas.js"></script>
document.getElementById('empezar').addEventListener('click', empezar) document.getElementById('carta').addEventListener('click', () => { cartas(1) }) document.getElementById('carta5').addEventListener('click', () => { cartas(5) }) let baraja function empezar () { fetch('https://deckofcardsapi.com/api/deck/new/shuffle/?deck_count=1') .then(response => response.json()) .then(json => { console.log(json) baraja = json.deck_id document.getElementById('mensaje').innerHTML = 'Tienes la baraja: ' + baraja }) .catch(err => { console.log('Error: ', err) }) } function cartas (num) { fetch('https://deckofcardsapi.com/api/deck/' + baraja + '/draw/?count=' + num) .then(response => response.json()) .then(json => { console.log(json) for (let i = 0; i < json.cards.length; i++) { const imagen = document.createElement('img') imagen.src = json.cards[i].image document.getElementById('cartas').appendChild(imagen) } }) .catch(err => { console.log('Error: ', err) }) }
Otro ejemplo Promise
console.log("Inicio script"); function benchmark() { return new Promise(function (resolve, reject) { let t=0; for (let i=0; i<10000; i++) { for (let j=0; j<100000; j++) { t++; } } console.log(t); resolve(t); }); } console.log("Creo promesa"); let test=benchmark(); console.log("Suscripción"); test.then((result) => { console.log("resuelto"); console.log(result); }) console.log("Fin script");
Ejercicio benchmark
En el ejercicio de clicar números hemos generado un array aleatorio y para ello hemos visto diferentes formas:
1.- Generar un número aleatorio e introducirlo en el array si no está, si ya está buscar otro número aleatorio.
2.- Crear un array correlativo y ordenarlo (sort) con random
3.- Utilizar el algoritmo Fisher-Yates (https://dev.to/codebubb/how-to-shuffle-an-array-in-javascript-2ikj)
4.- Otros, como el Durstenfeld, que mejora el Fisher Yates (este y más aquí: https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array)
Nos gustaría saber cual es más rápido y vamos a realizar un benchmark de estas 4 (o más) funciones. Definiremos una función a la que le pasamos el tamaño del array y nos devolverá un array desordenado de ese tamaño.
Una vez tengamos las funciones mediremos el tiempo, para ello ejecutaremos 1000 veces cada función para tamaños de 100, 1000, 10000 y 100000 elementos. Miraremos cual es la función más rápida para cada uno de estos tamaños.
Con el conocimiento adquirido crear una clase benchmark que en el constructor le pasemos como parámetros la función a evaluar y un array con el número de elementos (por defecto los mismos que antes). También tendrá una propiedad ‘times’ que por defecto vale 1000 pero que tendrá getter y setter. Esta clase tendrá un método getDurations que nos devolverá el resultado de ejecutar ‘times’ veces la función para cada uno de los tamaños que le pasamos por el array.