Javascript 我有多个iFrame,如何检测第一个加载的iFrame

Javascript 我有多个iFrame,如何检测第一个加载的iFrame,javascript,html,iframe,Javascript,Html,Iframe,我正在动态创建iFrame以显示通过url获得的文档。每个文档都在一个iframe中,而iframe又在一个div中。我有一个选项卡栏,允许在隐藏其余文档的同时显示任何文档,这是一个典型的选项卡式页面 我想显示包含接收第一个响应的iframe的div,即显示加载的第一个响应并隐藏其余响应。没有办法预测哪一个将首先加载,所以我需要一种方法来检测第一个并显示它,隐藏所有其余的 我想我可以通过让iframe onload函数在第一个onload处理程序运行时检查一个设置为true的全局布尔值来实现这一

我正在动态创建iFrame以显示通过url获得的文档。每个文档都在一个iframe中,而iframe又在一个div中。我有一个选项卡栏,允许在隐藏其余文档的同时显示任何文档,这是一个典型的选项卡式页面

我想显示包含接收第一个响应的iframe的div,即显示加载的第一个响应并隐藏其余响应。没有办法预测哪一个将首先加载,所以我需要一种方法来检测第一个并显示它,隐藏所有其余的

我想我可以通过让iframe onload函数在第一个onload处理程序运行时检查一个设置为true的全局布尔值来实现这一点

我不知道为什么,但这感觉很容易出错。有更好的方法吗

var firstDocumentReceived = false ; 
function buildFileTabs(evt) {
    firstDocumentReceived = false ;
    var files = evt.target.files;       // files is a list of File objects. 

    for (var i = 0, f; f = files[i]; i++) {
        addTab ( files[i].name );
    }

// create a div to display the requested document
function addTab ( fileName ) {
    var newDiv = document.createElement("div");
    newDiv.id = fileName.replace(".","_") + newRandomNumber() ; 

    // create an iframe to place in the div
    var newIframe = document.createElement("iframe");
    newIframe.onload=iframeLoaded ;
    newIframe.setAttribute("seamless", true );
    newIframe.setAttribute("div_id" , newDiv.id) ;
    newIframe.src = url ; // the iframe will contain a web page returned by the FDS server

    // nest the iframe in the div element
    newDiv.appendChild(newIframe) ;

    // nest the div element in the parent div
    document.getElementById("documentDisplay").appendChild(newDiv) ;
    ...

function iframeLoaded ( event ) {
    if ( firstDocumentReceived === false ) {
        firstDocumentReceived = true ;
        // show the div associated with this event
    } else {
        // hide the div associated with this event
    }

下面,我将介绍两种可选方法(A和B),您可以解析加载的第一个iframe:

A)在加载第一个iframe时停止加载其他iframe。

您需要设置一种跟踪正在添加的新iFrame的方法,例如下面显示的
newIframes
数组。您可以通过跟踪
newiframe
或在
iframeload()
函数中运行以下逻辑之前从DOM中检索它们来实现这一点

下面是一个示例,说明如何通过循环其他iframe来修改
iframeload()
函数,停止加载并隐藏它们:

function iframeLoaded(evt) {
  newIframes.forEach(function (newIframe) {
    if (newIframe.getAttribute('div_id') !== evt.target.getAttribute('div_id')) {
      // stop loading and hide the other iframes
      if (navigator.appName === 'Microsoft Internet Explorer') {
        newIframe.document.execCommand('Stop');
      } else {
        newIframe.stop();
      }
      newIframe.setAttribute('hidden', 'true'); // you can also delete it or set the css display to none
    }
  });
}
B)按照joews的建议使用
Promise.race()

承诺可以使用jQuery创建,但是ES6 harmony包含了一个对象的方法。基本上,完成的第一个承诺是在承诺之间的竞争中解决的

以下是如何修改代码以使用此ES6功能的示例:

1)创建一个新函数
createIframePromission()
,该函数为iframe创建承诺。

2)在外部作用域中创建一个空数组以保存不同的iframe承诺。

3)通过创建iframe承诺,然后将其推送到
iframe承诺
数组,修改您的
addTab()
函数。

确保同时删除行
newIframe.onload=iframeloadcreateIframePromise()
函数

4)在创建iFrame并将其承诺存储在
iFramePromissions
数组中后,修改您的
buildFileTabs()
函数以设置竞赛。


你控制iframes的内容吗?可能是Joe的副本,不确定你在问什么。iframe内容由服务器返回,但我不知道内容是什么。我只知道传递给服务器的文件名。如果您可以使用ES6(或Promise polyfill),这就是为解决此类问题而设计的。@joews,这是一个好方法@用户903724,我已经修改了我的答案,包括如何使用ES6
Promise.race()
。Boombox,感谢您深思熟虑的回复。Re:更安全的代码,我应该考虑一个闭包来处理获取/设置FrimeDigg标志吗?如果你的意思是<代码>第一个文档接收到的<代码>,你可以在一个iFILE中包装你的问题中显示的代码。这确保了
firstDocumentReceived
不会污染全局环境,并防止IIFE之外的另一段代码无意中使用或设置相同的
firstDocumentReceived
变量。避免在全局命名空间中声明变量通常是一个好主意。
function createIframePromise(newIframe) {
    var iframePromise = new Promise(function (resolve, reject) {
        newIframe.onload = function (evt) {
            // when the iframe finish loading, 
            // resolve with the iframe's identifier.
            resolve(evt.target.getAttribute('div_id'));
        }
    });
    return iframePromise;
}
// hold the iframe promises.
var iframePromises = []; 
function addTab(fileName) {
    // after "newIframe" with properties is created,
    // create its promise and push it to the array.
    iframePromises.push(createIframePromise(newIframe));
    // ...
}
function buildFileTabs(evt) {
    // ...
    Promise.race(iframePromises).then(function (firstIframeId) {
        // resolve...
        // put logic to show the first loaded iframe here. 
        // (all other iframe promises lose the race)
    }, function () {
        // reject...
        // nothing b/c "createIframePromise()" doesn't reject anything.
    });
}