I'm writing a Javascript script. This script will probably be loaded asynchronously (AMD format).
In this script, I'd like to do nothing important until the window.load
event was fired. 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?
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.
Than someone insert in this doc a tag, and this script tag loads my Javascript file.
This will execute my script.
How this script can know if window.load was already fired ?
No jQuery, not any script in the HTML doc before mine.
Is it possible to know ??
I found the window.document.readystate
property. 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
To quickly answer the question's title:
document.readyState === 'complete'
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. 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()'?
Igor brought up an interesting issue in the comments, which the following code can try to handle given a best-effort-timeout.
The problem is that the document.readyState
can be complete
before the load
event fires. I'm not certain what potential problems this may cause.
Complete: The state indicates that the load event is about to fire.
Gives a live example of event firing ie:
- readyState:
interactive
- Event Fired:
DOMContentLoaded
- readyState:
complete
- Event Fired:
load
There's a brief moment where the readyState
may be complete
before load
fires. 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
. By default it will wait 200ms before checking the readyState
. If the load
event fires before the timeout
we make sure to prevent firing the callback again. 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.
Depending on what you're trying to accomplish you may want to run the load
callback no matter what (remove the if (!called) {
check). 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.
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:
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:
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 . 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 .
EDIT: Here is a good answer already on StackOverflow:
How to check if DOM is ready without a framework?
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.
// 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:
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
Based on @CTS_AE's approach, I have put together a solution for envrionments where:
window.addEventListener('load', activateMyFunction);
andwindow.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:
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 = function(){
window.loaded = true;
window._load();
}
Then check for
if (window.loaded != undefined && window.loaded == true){
//do stuff
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.