在Chrome中加载iframe时,“加载”事件未触发

时间:2013-12-13 17:42:15

标签: javascript google-chrome angularjs iframe

我正在尝试在客户端上显示“掩码”,而文件是在服务器端动态生成的。似乎推荐解决此问题(因为它不是ajax)是使用iframe并从onload或done事件中侦听以确定文件何时实际从服务器传送到客户端。

这是我的角度代码:

    var url = // url to my api
    var e = angular.element("<iframe style='display:none' src=" + url + "></iframe>");
    e.load(function() {
        $scope.$apply(function() {
            $scope.exporting = false;  // this will remove the mask/spinner
        });
    });
    angular.element('body').append(e);

这在Firefox中运行良好但在Chrome中没有运气。我也试过使用onload函数:

e.onload = function()  { //unmask here }

但我也没有运气。

想法?

6 个答案:

答案 0 :(得分:20)

很遗憾,如果内容是附件,则无法在Chrome中使用iframe的onload事件。这个answer可以让您了解如何解决它。

答案 1 :(得分:10)

我讨厌这个,但除了每隔一段时间检查一次之外,除了检查它是否仍在加载之外,我找不到任何其他方式。

var timer = setInterval(function () {
    iframe = document.getElementById('iframedownload');
    var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
    // Check if loading is complete
    if (iframeDoc.readyState == 'complete' || iframeDoc.readyState == 'interactive') {
        loadingOff();
        clearInterval(timer);
        return;
    }
}, 4000);

答案 2 :(得分:4)

你可以用另一种方式做到:

在主要文件中:

function iframeLoaded() {
     $scope.$apply(function() {
            $scope.exporting = false;  // this will remove the mask/spinner
        });
}

var url = // url to my api
var e = angular.element("<iframe style='display:none' src=" + url + "></iframe>");
angular.element('body').append(e);

在iframe文档中(这是在url引用的页面的html内)

    window.onload = function() {
        parent.iframeLoaded();
    }

如果主页面和iframe内的页面位于同一个域中,这将有效。

实际上,您可以通过以下方式访问父级:

window.parent
parent
//and, if the parent is the top-level document, and not inside another frame
top          
window.top

使用window.parent更安全,因为变量parenttop可能会被覆盖(通常不是意图)。

答案 3 :(得分:0)

你必须考虑2分:

1-首先,如果您的网址具有不同的域名,则除非您有权访问其他域以添加Access-Control-Allow-Origin: *标头,否则无法执行此操作,要解决此问题,请转到此{ {3}}

2-但如果它具有相同的域名,或者您已将Access-Control-Allow-Origin: *添加到域名的标题中,则可以执行以下操作:

var url = // url to my api
var e = angular.element("<iframe style='display:none' src=" + url + "></iframe>");
angular.element(document.body).append(e);
e[0].contentWindow.onload = function() {
    $scope.$apply(function() {
        $scope.exporting = false;  // this will remove the mask/spinner
    });
};

我已在各种浏览器中完成此操作。

答案 4 :(得分:0)

我刚刚注意到Chrome并不总是触发主页面的加载事件,所以这可能会对iframe产生影响,因为它们的处理基本相同。

使用Dev Tools或Performance api检查是否正在触发加载事件。

我刚检查了http://ee.co.uk/,如果你打开控制台并输入window.performance.timing,你会发现domComplete,loadEventStart和loadEventEnd的条目都是0 - 至少在当前时间:)

看起来这里的Chrome存在问题 - 我在2台电脑上使用最新版本31.0.1650.63进行了检查。

更新:再次检查ee并加载事件但未在后续重新加载时触发,因此这是间歇性的,可能与其网站上的加载错误有关。但是加载事件应该触发任何东西。

由于我发现自己的网站监控偶尔会失败,所以在最后一天我在5或6个网站上发生了这个问题。只是找到了原因。我需要一些美容睡眠然后当我更清醒的时候我会进一步调查。

答案 5 :(得分:0)

我遇到了 iframe 加载时间过长的问题。在未处理请求时注册为已加载的 iframe。我想出了以下解决方案:

JS

功能:

function iframeReloaded(iframe, callback) {
    let state = iframe.contentDocument.readyState;
    let checkLoad = setInterval(() => {
        if (state !== iframe.contentDocument.readyState) {
            if (iframe.contentDocument.readyState === 'complete') {
                clearInterval(checkLoad);
                callback();
            }
            state = iframe.contentDocument.readyState;
        }
    }, 200)
}

用法:

iframeReloaded(iframe[0], function () {
    console.log('Reloaded');
})

JQuery

功能:

$.fn.iframeReloaded = function (callback) {
    if (!this.is('iframe')) {
        throw new Error('The element is not an iFrame, please provide the correct element');
    }

    let iframe = this[0];
    let state = iframe.contentDocument.readyState;
    let checkLoad = setInterval(() => {
        if (state !== iframe.contentDocument.readyState) {
            if (iframe.contentDocument.readyState === 'complete') {
                clearInterval(checkLoad);
                callback();
            }
            state = iframe.contentDocument.readyState;
        }
    }, 200)
}

用法:

iframe.iframeReloaded(function () {
    console.log('Reloaded');
})