Tengo una matriz de URL de imágenes y quiero mostrar estas imágenes en la página web en el orden de ubicación de su URL correspondiente en la matriz.
por ejemplo, tenemos
const imgUrls = [ "https://picsum.photos/400/400", "https://picsum.photos/200/200", "https://picsum.photos/300/300" ]; en cuyo caso queremos mostrar primero 400/400 , luego 200/200 y por último 300/300 .
Si lo implementamos ingenuamente, el orden no está garantizado.
function loadImages(imgUrls, root) { imgUrls.forEach((url) => { const image = document.createElement("img"); image.onload = () => { root.append(image); }; image.src = url; }); }Así que uso Promises para administrar el control de flujo asíncrono
async function loadImagesInOrder(imgUrls, rootEl) { const promises = imgUrls.map( (url) => new Promise((resolve, reject) => { const image = document.createElement("img"); image.onload = resolve; image.onerror = reject; image.src = url; }) ); for (const p of promises) { const { currentTarget } = await p; rootEl.append(currentTarget); } } Funciona, pero no todo el tiempo. Con esta implementación, a veces algunas imágenes serán null , por lo que terminará con un null en la página web.
Esta es la demostración en vivo https://codesandbox.io/s/load-images-in-order-t16hs?file=/src/index.js
¿Alguien puede señalar cuál es el problema? Además , ¿hay alguna forma mejor de asegurarse de que la imagen aparezca en la página en el orden de la URL en la matriz?
Parece que el .currentTarget del evento a veces es null por algún motivo. Una solución fácil es resolver la Promesa con la imagen misma, en lugar de pasar por el controlador de load problemático. Keith encontró por qué en los comentarios:
Nota: El valor de event.currentTarget solo está disponible mientras se maneja el evento.
pero cuando lo haces
for (const p of promises) { const { currentTarget } = await p; rootEl.append(currentTarget); } El proceso de carga de todas las imágenes se inicia inmediatamente , pero se cargan de forma asincrónica y, a menudo, no se cargan en orden. El .currentTarget no existirá si Promise se resuelve después de que la imagen ya se haya cargado; por ejemplo, si se carga la imagen 1, luego se carga la imagen 3, luego se carga la imagen 2, la imagen 3 ya se habrá cargado en el momento en que se carga la tercera imagen.
const { currentTarget } = await p;carreras.
Si simplemente necesita ordenar las imágenes correctamente al final, un enfoque más fácil sería agregarlas de inmediato.
const root = document.querySelector("#app"); const imgUrls = [ "https://picsum.photos/400/400", "https://picsum.photos/200/200", "https://picsum.photos/300/300" ]; for (const src of imgUrls) { root.appendChild(document.createElement('img')).src = src; } <div id="app">