Как получить ВСЕ 404 при загрузке изображений - PullRequest
0 голосов
/ 06 апреля 2020

Проблема:

У меня есть веб-страница, которая загружает много изображений из внешних источников. Некоторые из этих ссылок на изображения могут быть повреждены, и у меня есть скрипт, который вызывается через атрибут onerror, который удаляет изображение (и некоторый связанный контент, такой как заголовок, некоторые теги ...), если оно не загружается.

Это работает нормально в большинстве случаев, ЗА ИСКЛЮЧЕНИЕМ, когда сервер изображений отправляет мне изображение по умолчанию для замены отсутствующего. В этом случае событие onerror не запускается, и моя страница получает уродливое изображение по умолчанию.

Что я хочу сделать:

Я хочу иметь возможность обнаруживать и избавляться от эти изображения.

Вопросы:

1) Есть ли способ определить код состояния (404) загрузки изображения из тега img? (Из проведенных мною исследований это кажется невозможным, но я все еще спрашиваю ...).

2) Если № 1 невозможен, кажется, что одним из решений являются вызовы для загрузки изображения с чем-то вроде XMLHttpRequest и взглядом на код ответа. В этом случае:

  • есть ли более подходящий способ, чем XMLHttpRequest?

  • , если я ожидаю много проблем от CORS?

Для справки, вот черновик решения, основанный на XMLHttpRequest:

function imgLoad(url, onOk, onProblem) {
    'use strict';

    var request = new XMLHttpRequest();
    request.open('GET', url);
    request.responseType = 'blob';

    request.onload = function () {
        if (request.status === 200) {

            onOk(request.response);

        } else {

            onProblem();

        }
    };

    request.onerror = function () {
        // if the request fails

        onProblem();
    };

    request.send();
};


function onOk(response) {

    var body = document.querySelector('body');
    var myImage = new Image();
    myImage.crossOrigin = ""; // or "anonymous"

    var imageURL = window.URL.createObjectURL(response);

    myImage.src = imageURL;
    body.appendChild(myImage);
};

function onProblem(err) {
    // remove the image and the other related elements
};

function loadImage(url) {
    'use strict';

    imgLoad(url, onOk, onProblem);
};

Редактировать:

Чтобы ответить на @Oo, фактическое код выглядит примерно так:

image

Просто простой тег img. Функция imgError - это та, которая удаляет элементы, связанные с изображением, если оно не загружается. Но это не работает, если возвращается изображение по умолчанию, только если НЕТ изображение не возвращается.

1 Ответ

0 голосов
/ 20 апреля 2020

Вот реальное решение, которое я реализовал. В то же время я добавил ленивую загрузку для изображений. Вот код, на случай, если он кому-нибудь поможет:


/**
* this function load the image using an XMLHttpRequest to be able to read the status code from javascript.
*/

function imgLoad(image, onOk, onError) {

    var url = image.dataset.src;

    var request = new XMLHttpRequest();
    request.open('GET', url);
    request.responseType = 'blob';

    request.onload = function () {
        if (request.status === 200) {

            onOk(request.response, image);
        } else {

            onError(image);
        }
    };

    request.onerror = function () {
        // if the request fails
        onError(image);
    };

    request.send();
};


/**
* This function is called if the image successfully loads. It just replace the "src" prop and the image is pulled from the cache from the browser.
*/

function onOk(response, image) {

    image.crossOrigin = ""; // or "anonymous"

    var imageURL = window.URL.createObjectURL(response);

    //image.src = imageURL;  // to use the blob response
    image.src = image.dataset.src;  // to use normal src and disk cache
    image.onerror = "";
    image.classList.remove("lazy");
};

/**
* small helper
*/
function loadImage(image) {

    imgLoad(image, onOk, imgError);
};


/**
* wrap up and lazy loading implementation
*/
document.addEventListener("DOMContentLoaded", function() {
    var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

    if ("IntersectionObserver" in window) {
      let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
        entries.forEach(function(entry) {
          if (entry.isIntersecting) {
            let lazyImage = entry.target;

            loadImage(lazyImage);

            lazyImageObserver.unobserve(lazyImage);
          }
        });
      });

      lazyImages.forEach(function(lazyImage) {
        lazyImageObserver.observe(lazyImage);
      });
    } else {
      // fall back
      lazyImages.forEach(function(lazyImage) {
        loadImage(lazyImage);
      });
    }
  });

Я не включил функцию "onError", потому что она очень специфична c для моего кода и здесь не очень важна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...