Загрузить изображение без «new Image ()» - PullRequest
0 голосов
/ 10 мая 2019

Я пытаюсь загрузить изображение в JavaScript:

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

img был создан ранее, но еще не существует в DOM. Он должен быть добавлен после загрузки.

Моя проблема: Насколько я понимаю, он на самом деле не собирается загружать изображение, потому что элемент еще не является частью DOM.


Я попытался использовать new Image(), потому что это загрузит источник изображения перед вставкой в ​​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;
  });
}

Однако, это делало загрузку дважды и чувствовало себя глючным.

Мне нужно сохранить (и использовать) элемент img, так как к нему прикреплены другие обработчики событий и атрибуты.

Что я могу сделать, чтобы загрузить изображение и выполнить обещание, как только оно будет выполнено?

Ответы [ 3 ]

1 голос
/ 10 мая 2019

Не уверен, что не так с вашим вторым подходом и почему вы думаете, что он глючит.Я могу представить, что он загружается дважды, если изображение еще не находится в кеше: если вы запускаете загрузку двух изображений одновременно, браузер не может знать параметры кэширования URL-адреса и должен загрузить его для обоих элементов отдельно.Но если вы загружаете их последовательно, второй должен извлекать из кэша, а не делать отдельный запрос, кроме случаев, когда ваш сервер работает странно и обслуживает заголовки, которые запрещают кэширование.

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">
0 голосов
/ 10 мая 2019

Я думаю, что ваше предположение неверно. Изображение загружается без необходимости его подключения к DOM.

Я немного изменил вашу функцию, чтобы она разрешалась с помощью тега изображения вместо события загрузки, и, похоже, она работает нормально:

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

}

Я проверяю это так:

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);
  })

deelay.me добавляет искусственную задержку к загрузке изображения, поэтому вы можете видеть, что изображение действительно загружено и, используя обещание, присоединяется к DOM только после его загрузки.

Надеюсь, это поможет.

Fiddle: https://jsfiddle.net/f4hratje/5/

0 голосов
/ 10 мая 2019

Если я правильно вас понимаю, вы хотите отрендерить изображение после того, как загрузка будет завершена?Может быть, просто создать изображение в функции «loadImage», а затем в «onload» сделать соответствующее добавление.Вот пример того, о чем я думал:

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/

...