首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >检测加载iframe内容失败

检测加载iframe内容失败
EN

Stack Overflow用户
提问于 2008-12-17 19:20:59
回答 6查看 48.2K关注 0票数 61

我可以使用load事件检测iframe的内容何时加载。不幸的是,就我的目的而言,这有两个问题:

  • 如果加载页面(404/500等)时出错,则永远不会触发load事件。
  • 如果某些图像或其他依赖项加载失败,则会照常触发load事件。

有没有什么方法可以可靠地确定上面的错误是否发生了?

我正在编写一个基于Mozilla/XULRunner的半web半桌面应用程序,因此欢迎只在Mozilla中工作的解决方案。

EN

回答 6

Stack Overflow用户

发布于 2008-12-17 19:38:50

如果您可以控制iframe页面(并且这些页面位于相同的域名上),则可以采用以下策略:

在父文档中,初始化加载iframe文档的变量,将父文档中的此变量设置为使用timer对象从iframe文档调用父函数true (setIFrameLoaded(); var iFrameLoaded = false;

  • When example).

  • check iFrameLoaded标志(将计时器设置为您首选的超时限制)-如果该标志仍然为false,则可以断定未定期加载iframe。

我希望这能帮到你。

票数 14
EN

Stack Overflow用户

发布于 2008-12-22 16:29:24

我最近遇到了这个问题,不得不在父页面(包含IFRAME标签)上设置一个Javascript轮询操作。此JavaScript函数检查IFRAME的内容,查找应该只存在于良好响应中的显式元素。当然,这假设您不必处理违反“同源策略”的问题。

而不是检查可能从许多不同的网络资源产生的所有可能的错误。我只是简单地检查了一个常量的积极因素,我知道应该是一个良好的反应。

在预先确定的时间和/或尝试检测预期元素的失败次数之后,JavaScript修改IFRAME的SRC属性(从我的Servlet请求一个用户友好的错误页面),而不是显示典型的HTTP错误消息。JavaScript还可以很容易地修改SRC属性以发出完全不同的请求。

代码语言:javascript
复制
function checkForContents(){
var contents=document.getElementById('myiframe').contentWindow.document
if(contents){
    alert('found contents of myiframe:' + contents);
    if(contents.documentElement){
        if(contents.documentElement.innerHTML){
            alert("Found contents: " +contents.documentElement.innerHTML);
            if(contents.documentElement.innerHTML.indexOf("FIND_ME") > -1){
                openMediumWindow("woot.html", "mypopup");
            }
        }
    }
}

}

票数 8
EN

Stack Overflow用户

发布于 2019-03-02 06:09:54

这是一个非常晚的答案,但我会把它留给需要它的人。

任务:加载iframe跨域内容,成功时发出onLoaded,加载错误时发出onError

这是我能开发的最具跨浏览器来源独立的解决方案。但首先,我将简要介绍一下我曾经使用过的其他方法,以及它们为什么不好。

iframe这对我来说有点震惊,那个iframe只有onload事件,它在加载和错误时被调用,没有办法知道它是不是错误。

performance.getEntriesByType('resource'). 2.此方法返回加载的资源。听起来就是我们需要的。但遗憾的是,firefox总是在资源数组中添加资源,无论它是加载还是失败。没有办法通过Resource实例知道它是否成功。像往常一样。顺便说一句,这种方法在ios<11中不起作用。

3.script我尝试使用<script>标签加载。遗憾的是,只有在Chrome中才能正确地发射onloadonerror

当我准备放弃的时候,我的学长告诉我关于html4 tag <object>的事情。它类似于<iframe>标签,除了在内容未加载时有回退。这听起来就是我们需要的!遗憾的是,这并不像听起来那么容易。

代码段

代码语言:javascript
复制
var obj = document.createElement('object');

// we need to specify a callback (i will mention why later)
obj.innerHTML = '<div style="height:5px"><div/>'; // fallback

obj.style.display = 'block'; // so height=5px will work
obj.style.visibility = 'hidden'; // to hide before loaded

obj.data = src;

在此之后,我们可以像对iframe一样设置一些属性给<object>。唯一的区别是,我们应该使用<params>,而不是属性,但它们的名称和值是相同的。

代码语言:javascript
复制
for (var prop in params) {
    if (params.hasOwnProperty(prop)) {
        var param = document.createElement('param');
        param.name = prop;
        param.value = params[prop];

        obj.appendChild(param);
    }
}

现在,最难的部分。与许多类似的元素一样,<object>没有回调规范,因此每个浏览器的行为都不同。

  • Chrome.On error和on load发出load event.
  • Firefox.发出loaderror correctly.
  • Safari.不会发出任何信号...

看起来和iframegetEntriesByTypescript没有什么不同。但是,我们有本机浏览器回退!因此,因为我们直接设置了回退(innerHtml),所以我们可以判断是否加载了<object>

代码语言:javascript
复制
function isReallyLoaded(obj) {
    return obj.offsetHeight !== 5; // fallback height
}
代码语言:javascript
复制
/**
 * Chrome calls always, Firefox on load
 */
obj.onload = function() {
    isReallyLoaded(obj) ? onLoaded() : onError();
};

/**
 * Firefox on error
 */
obj.onerror = function() {
    onError();
};

但是如何处理Safari呢?很好的老setTimeout

代码语言:javascript
复制
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;
}

是啊……还没那么快。问题是,<object>在失败时有规范中没有提到的行为:

尝试加载(size=0)

  • Fails (size = any) really

  • Fallback (size = as in innnerHtml)

的大小

因此,代码需要一些增强。

代码语言:javascript
复制
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);

好的,然后开始加载

代码语言:javascript
复制
document.body.appendChild(obj);

,这都是。我试图解释代码的每一个细节,这样看起来就不那么愚蠢了。

P.S. WebDev烂透了

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/375710

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档