Estoy tratando de cargar una imagen en JavaScript:

loadImage(src, img) {
  return new Promise((resolve, reject) => {
    img.onload = resolve;
    img.onerror = reject;
    img.src = src;
  });
}

El img se ha creado antes, pero aún no existe en el DOM. Debe agregarse una vez que se haya cargado.

Mi problema: por lo que entiendo, en realidad no va a cargar la imagen, porque el elemento aún no es parte del DOM.


Intenté usar new Image(), porque esto cargará la fuente de la imagen antes de insertarla en el DOM:

loadImage(src, img) {
  return new Promise((resolve, reject) => {
    var tmp = new Image();

    tmp.onload = resolve;
    tmp.onerror = reject;
    tmp.src = src;
    img.src = src;
  });
}

Sin embargo, esto hizo la carga dos veces y se sintió con errores.

Necesito mantener (y usar) el elemento img, ya que otros controladores de eventos y atributos están asociados a él.

¿Qué puedo hacer para cargar la imagen y resolver la promesa una vez que está hecha?

0
Andreas Remdt 10 may. 2019 a las 15:45

3 respuestas

La mejor respuesta

No estoy seguro de lo que está mal con su segundo enfoque y por qué cree que tiene errores. Puedo imaginar que se cargue dos veces si la imagen aún no está en caché: si activa la carga de dos imágenes al mismo tiempo, el navegador no puede conocer los parámetros de almacenamiento en caché de la URL, y debería cargarla para ambos elementos por separado. Pero si los carga en secuencia, el segundo debe extraerse del caché y no realizar una solicitud por separado, excepto si su servidor es extraño y sirve encabezados que prohíben el almacenamiento en caché.

function loadImage(src, img) {
  return new Promise((resolve, reject) => {
    var tmp = new Image();

    tmp.onload = () => {
      img.src = src;
      resolve();
    };
    tmp.onerror = reject;
    tmp.src = src;
  });
}

loadImage("https://via.placeholder.com/350x150", document.getElementById('foo'));
<image id="foo">
1
Amadan 10 may. 2019 a las 13:16

Si te entiendo correctamente, ¿quieres renderizar la imagen una vez que haya terminado de cargarse? Tal vez solo cree la imagen en la función "loadImage" y luego en la "carga" haga el apéndice apropiado. Aquí hay un ejemplo de lo que estaba pensando:

const loadImage = (src, parentEl) => {
const img = document.createElement('img')
img.src = src
img.onload = () => {
  parentEl.appendChild(img)
 }
}

const parentEl = document.getElementById('parent')
loadImage('https://fakeimg.pl/640x360', parentEl)

https://jsfiddle.net/2Lp8hyxf/

0
kimito 10 may. 2019 a las 13:03

Creo que su suposición es incorrecta. La imagen se carga sin que sea necesario adjuntarla al DOM.

Modifiqué su función ligeramente para que se resuelva con la etiqueta de imagen en lugar del evento de carga y parece estar funcionando bien:

const loadImage = (src, img) => {
    return new Promise((resolve, reject)=> {
    img.src = src
    img.onload = () => {
        resolve(img);
    }
    img.onerror = reject;
  })

}

Lo estoy probando así:

const img = document.createElement('img');
loadImage('http://deelay.me/1500/https://fakeimg.pl/640x360', img)
    .then((img) => {
    const parent = document.getElementById('parent');
    document.getElementById('parent').append(img);
    const text = document.createElement('p');
    text.innerText = "The promise resolved now";
    parent.append(text);
  })

El deelay.me agrega un retraso artificial a la carga de la imagen, para que pueda ver que la imagen está realmente cargada y, usando la promesa, se adjunta al DOM solo después de que se ha cargado.

Espero que esto ayude.

Violín: https://jsfiddle.net/f4hratje/5/

0
Alex 10 may. 2019 a las 13:17