这是一个很晚的答案,但是我将其留给需要它的人。
任务:加载iframe跨域内容,成功时发出,错误时发出getEntriesByType。
这是我可以开发的跨浏览器最独立的解决方案。 但是首先,我将简要介绍一下我使用的其他方法以及它们为什么不好。
1. iframe这让我有些震惊,因为iframe仅具有事件,并且在加载和出错时被调用,无法知道它是否出错。
2. performance.getEntriesByType('resource')。 此方法返回已加载的资源。 听起来像我们需要的。 但是可惜的是,firefox总是在资源数组中添加资源,无论它是加载还是失败。 通过实例无法知道它是否成功。 照常。 顺便说一句,此方法在ios <11中不起作用。
3.我尝试使用标签加载html的脚本。 不幸的是,仅在Chrome中正确发出getEntriesByType和script。
当我准备放弃时,我的老同事告诉我html4标签getEntriesByType标签。它像getEntriesByType标签一样,除了在未加载内容时会回退。 这听起来像我们所需要的! 可悲的是,它并不像听起来那样容易。
代码部分
var obj = document.createElement('object');
// we need to specify a callback (i will mention why later)
obj.innerHTML = '
obj.style.display = 'block'; // so height=5px will work
obj.style.visibility = 'hidden'; // to hide before loaded
obj.data = src;
此后,我们可以像想对getEntriesByType009那样设置一些属性到。唯一的区别是,我们应该使用2691178263212459059010,而不是属性,但是它们的名称和值是相同的。
for (var prop in params) {
if (params.hasOwnProperty(prop)) {
var param = document.createElement('param');
param.name = prop;
param.value = params[prop];
obj.appendChild(param);
}
}
现在,困难的部分。 与许多相同元素一样,也没有回调规范,因此每个浏览器的行为都不同。
铬。 在错误和负载下会发出事件。
火狐浏览器。 正确发出和getEntriesByType。
苹果浏览器。 什么都没发出...
似乎与、getEntriesByType、script没有什么不同....但是,我们有本机浏览器后备功能! 因此,因为我们直接设置了后备(innerHtml),所以可以判断是否已加载
function isReallyLoaded(obj) {
return obj.offsetHeight !== 5; // fallback height
}
/**
* Chrome calls always, Firefox on load
*/
obj.onload = function() {
isReallyLoaded(obj) ? onLoaded() : onError();
};
/**
* Firefox on error
*/
obj.onerror = function() {
onError();
};
但是,使用Safari怎么办? 好老。
var interval = function() {
if (isLoaded) { // some flag
return;
}
if (hasResult(obj)) {
if (isReallyLoaded(obj)) {
onLoaded();
} else {
onError();
}
}
setTimeout(interval, 100);
};
function hasResult(obj) {
return obj.offsetHeight > 0;
}
是的。 问题是,发生故障时规范行为未提及:
尝试加载(大小= 0)
失败(大小=任何)
后备(大小=如innerHtml)
因此,代码需要一些增强
var interval = function() {
if (isLoaded) { // some flag
return;
}
if (hasResult(obj)) {
if (isReallyLoaded(obj)) {
interval.count++;
// needs less then 400ms to fallback
interval.count > 4 && onLoadedResult(obj, onLoaded);
} else {
onErrorResult(obj, onError);
}
}
setTimeout(interval, 100);
};
interval.count = 0;
setTimeout(interval, 100);
好了,开始加载
document.body.appendChild(obj);
就这些。 我试图详细解释代码,因此看起来似乎并不愚蠢。
附言 Web糟透了