如何在图像加载时获得 ALL 404

How to get ALL 404 on images loading

问题:

我有一个网页加载了大量来自外部来源的图像。其中一些图像链接可能会被破坏,我有一个脚本可以通过 onerror 属性调用,如果图像未加载,该脚本会删除图像(以及一些相关内容,如标题、一些标签...)。

在大多数情况下都可以正常工作,除非图像服务器向我发送默认图像以替换丢失的图像。在这种情况下,onerror 事件不会触发,我的页面会得到一个难看的默认图像。

我想做的事情:

我希望能够检测并删除这些图像。

问题:

1) 有没有办法检测从 img 标签加载图像的状态代码 (404)? (从我所做的研究来看,这似乎是不可能的,但我仍然在问......)。

2) 如果#1 不可能,一种解决方案似乎是调用加载图像 XMLHttpRequest 之类的东西并查看响应代码。在那种情况下:

作为参考,这是一个基于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);
};

编辑:

回复@O.o,实际代码是这样的:

<img src="http://someimageurl.jpg" onerror="imgError(this);">

只是一个简单的img标签。 imgError 函数是在图像未加载时删除与图像相关的元素的函数。但如果返回默认图片则不起作用,只有在没有返回图片的情况下才有效。

这是我实际实施的解决方案。同时我为图像添加了延迟加载。这是代码,以防对任何人有帮助:


/**
* 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" 函数,因为它非常适合我的代码,在这里不是特别相关。