如何在图像加载时获得 ALL 404
How to get ALL 404 on images loading
问题:
我有一个网页加载了大量来自外部来源的图像。其中一些图像链接可能会被破坏,我有一个脚本可以通过 onerror
属性调用,如果图像未加载,该脚本会删除图像(以及一些相关内容,如标题、一些标签...)。
在大多数情况下都可以正常工作,除非图像服务器向我发送默认图像以替换丢失的图像。在这种情况下,onerror
事件不会触发,我的页面会得到一个难看的默认图像。
我想做的事情:
我希望能够检测并删除这些图像。
问题:
1) 有没有办法检测从 img 标签加载图像的状态代码 (404)? (从我所做的研究来看,这似乎是不可能的,但我仍然在问......)。
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);
};
编辑:
回复@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" 函数,因为它非常适合我的代码,在这里不是特别相关。
问题:
我有一个网页加载了大量来自外部来源的图像。其中一些图像链接可能会被破坏,我有一个脚本可以通过 onerror
属性调用,如果图像未加载,该脚本会删除图像(以及一些相关内容,如标题、一些标签...)。
在大多数情况下都可以正常工作,除非图像服务器向我发送默认图像以替换丢失的图像。在这种情况下,onerror
事件不会触发,我的页面会得到一个难看的默认图像。
我想做的事情:
我希望能够检测并删除这些图像。
问题:
1) 有没有办法检测从 img 标签加载图像的状态代码 (404)? (从我所做的研究来看,这似乎是不可能的,但我仍然在问......)。
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);
};
编辑:
回复@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" 函数,因为它非常适合我的代码,在这里不是特别相关。