简体   繁体   English

如何知道窗口“加载”事件是否已经触发

[英]How to know if window "load" event was fired already

I'm writing a Javascript script.我正在编写一个 Javascript 脚本。 This script will probably be loaded asynchronously (AMD format).该脚本可能会异步加载(AMD 格式)。

In this script, I'd like to do nothing important until the window.load event was fired.在这个脚本中,在window.load事件被触发之前,我不想做任何重要的事情。 So I listen to the window "load" event.所以我听窗口“加载”事件。

But if the script is loaded after window.load event... how can I know window.load was already fired?但是如果脚本是在 window.load 事件之后加载的……我怎么知道window.load已经被触发了?

And of course I don't want to add something in any other scripts (they are all loaded async, the problem is the same) :)当然我不想在任何其他脚本中添加一些东西(它们都是异步加载的,问题是一样的):)

Edit :编辑 :

Imagine an HTML doc with no Javascript in it at all.想象一个完全没有 Javascript 的 HTML 文档。

Than someone insert in this doc a tag, and this script tag loads my Javascript file.比有人在这个文档中插入一个标签,这个脚本标签加载我的 Javascript 文件。

This will execute my script.这将执行我的脚本。

How this script can know if window.load was already fired ?这个脚本如何知道 window.load 是否已经被触发?

No jQuery, not any script in the HTML doc before mine.没有 jQuery,在我之前的 HTML 文档中没有任何脚本。

Is it possible to know ??有可能知道吗??

I found the window.document.readystate property.我找到了window.document.readystate属性。 This property is for document "ready" event I guess, not for window "load".我猜这个属性是针对文档“就绪”事件,而不是针对窗口“加载”。 Is there anything similar for window "load" event ?窗口“加载”事件有类似的东西吗?

最简单的解决方案可能是检查document.readyState == 'complete' ,请参阅http://www.w3schools.com/jsref/prop_doc_readystate.asp

Quick Answer快速回答

To quickly answer the question's title:要快速回答问题的标题:

document.readyState === 'complete'

Deeper Example更深层次的例子

Below is a nice helper if you want to call code upon a window load, while still handling the case where the window may have already loaded by the time your code runs.如果您想在窗口加载时调用代码,下面是一个很好的帮手,同时仍然处理在代码运行时窗口可能已经加载的情况。

 function winLoad(callback) { if (document.readyState === 'complete') { callback(); } else { window.addEventListener("load", callback); } } winLoad(function() { console.log('Window is loaded'); });

Note : code snippets on here actually don't run in the same window context so document.readyState === 'complete' actually evaluates to false when you run this.注意:此处的代码片段实际上不在同一个窗口上下文中运行,因此document.readyState === 'complete'在您运行它时实际上评估为false If you put the same into your console right now for this window it should evaluate as true.如果您现在为此窗口将相同的内容放入控制台,它应该评估为真。

See also : What is the non-jQuery equivalent of '$(document).ready()'?另请参阅'$(document).ready()' 的非 jQuery 等价物是什么?


Handling the Edge Case from @IgorBykov via Comments通过评论处理来自@IgorBykov 的边缘案例

Igor brought up an interesting issue in the comments, which the following code can try to handle given a best-effort-timeout. Igor 在评论中提出了一个有趣的问题,下面的代码可以尝试在尽力超时的情况下处理该问题。

The problem is that the document.readyState can be complete before the load event fires.问题是document.readyState可以在load事件触发之前complete I'm not certain what potential problems this may cause.我不确定这可能会导致什么潜在问题。

Some Documentation About the Flow and Event Firing关于流程和事件触发的一些文档

Complete: The state indicates that the load event is about to fire.

Gives a live example of event firing ie:给出了一个事件触发的实例,即:

  1. readyState: interactive就绪状态: interactive
  2. Event Fired: DOMContentLoaded事件触发: DOMContentLoaded
  3. readyState: complete就绪状态: complete
  4. Event Fired: load事件触发: load

There's a brief moment where the readyState may be complete before load fires.load触发之前, readyState可能会在短时间内complete I'm not sure what issues you may run into during this period.我不确定您在此期间可能会遇到什么问题。

The below code registers the load event listener, and sets a timeout to check the readyState .下面的代码注册了load事件监听器,并设置了一个超时来检查readyState By default it will wait 200ms before checking the readyState .默认情况下,它会在检查readyState之前等待 200 毫秒。 If the load event fires before the timeout we make sure to prevent firing the callback again.如果load事件在timeout之前触发,我们确保防止再次触发回调。 If we get to the end of the timeout and load wasn't fired we check the readyState and make sure to avoid a case where the load event could potentially still fire at a later time.如果我们到达timeout结束并且load没有被触发,我们检查readyState并确保避免load事件可能在以后触发的情况。

Depending on what you're trying to accomplish you may want to run the load callback no matter what (remove the if (!called) { check).根据您要完成的任务,您可能无论如何都需要运行load回调(删除if (!called) {检查)。 In your callback you might want to wrap potential code in a try/catch statement or check for something that you can gate the execution on so that when it calls twice it only performs the work when everything is available that you expect.在您的回调中,您可能希望将潜在代码包装在 try/catch 语句中,或者检查您可以控制执行的内容,以便当它调用两次时,它仅在您期望的一切可用时才执行工作。

 function winLoad(callback, timeout = 200) { let called = false; window.addEventListener("load", () => { if (!called) { called = true; callback(); } }); setTimeout(() => { if (!called && document.readyState === 'complete') { called = true; callback(); } }, timeout); } winLoad(function() { console.log('Window is loaded'); });

Browser navigation performance loadEventEnd metric can be used to determinate if load event was triggered:浏览器导航性能loadEventEnd 指标可用于确定是否触发了加载事件:

let navData = window.performance.getEntriesByType("navigation");
if (navData.length > 0 && navData[0].loadEventEnd > 0)
{
    console.log('Document is loaded');
} else {
    console.log('Document is not loaded');
}

Here is my answer: 这是我的答案:

fiddle 小提琴

window.addEventListener("load", function () {
    window.loaded = true;
});

function logLoaded() {
    console.log("loaded");
}

(function listen () {
    if (window.loaded) {
        logLoaded();
    } else {
        console.log("notLoaded");
        window.setTimeout(listen, 50);
    }
})();

You can read about addEventListener() and its compatibility (it is new to the ECMAScript 5 spec) here . 您可以在此处阅读addEventListener()及其兼容性(它是ECMAScript 5规范的新增内容)。 It is the new "preferred" way to do things going forward. 这是未来做事的新“首选”方式。

You can read about Immediately Invoked Function Expressions (IIFE) (alternately, self-invoked anonymous functions or immediately invoked anonymous functions) here . 你可以阅读有关立即调用函数表达式(IIFE)(交替,自我援引匿名函数或立即调用匿名函数) 这里

EDIT: Here is a good answer already on StackOverflow: 编辑:这是StackOverflow上的一个很好的答案:

How to check if DOM is ready without a framework? 如何在没有框架的情况下检查DOM是否准备就绪?

If you specifically want to know if the DOM load event has fired, set a global variable in a DOM 'load' event handler and then check for its existence when your new code loads. 如果您特别想知道DOM加载事件是否已触发,请在DOM“load”事件处理程序中设置一个全局变量,然后在加载新代码时检查它是否存在。

// in 'load' event handler
window.domLoadEventFired = true;

// in code you are loading asynchronously
if (typeof window.domLoadEventFired !== undefined) {
    // ...
}

If you don't want to use jQuery, the logic it uses is:如果你不想使用 jQuery,它使用的逻辑是:

if( !document.body )
    setTimeout( checkAgain, 1 );

So between the windows loaded event and checking if the body property of the document is available, you can check if the DOM is ready因此,在 windows 加载事件和检查文档的 body 属性是否可用之间,您可以检查 DOM 是否准备好

Based on @CTS_AE's approach, I have put together a solution for envrionments where:基于@CTS_AE 的方法,我为以下环境制定了一个解决方案:

  • window.addEventListener('load', activateMyFunction); and
  • window.addEventListener('DOMContentLoaded', activateMyFunction);

don't work.不工作。

It requires a single character substitution (eg. from它需要单个字符替换(例如,从

window.addEventListener('load', activateMyFunction);

to

window_addEventListener('load', activateMyFunction);)

The function window_addEventListener() looks like this:函数window_addEventListener()如下所示:

const window_addEventListener = (eventName, callback, useCapture = false) => {

  if ((document.readyState === 'interactive') || (document.readyState === 'complete'))   {

    callback();
  }
}

Easy method:简易方法:

window.onload = (event) => {
  console.log('page is fully loaded');
};

You can find other methods from resources here .您可以从这里的资源中找到其他方法。

what about overriding window.load?覆盖window.load怎么样?

window._load = window.load;
window.load = function(){
  window.loaded = true;
  window._load();
}

Then check for然后检查

if (window.loaded != undefined && window.loaded == true){
    //do stuff
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM