Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
285 views
in Technique[技术] by (71.8m points)

javascript - Async-loaded scripts with DOMContentLoaded or load event handlers not being called?

I've got a script with a DOMContentLoaded event handler—

document.addEventListener('DOMContentLoaded', function() {
    console.log('Hi');
});

Which I'm loading asynchronously—

<script async src=script.js></script>

However, the event handler is never called. If I load it synchronously—

<script src=script.js></script>

It works fine.

(Even if I change the DOMContentLoaded event to a load event, it's never called.)

What gives? The event handler should be registered irrespective of how the script is loaded by the browser, no?

Edit: It doesn't work on Chrome 18.0.1025.11 beta but, with DOMContentLoaded, it does on Firefox 11 beta (but with load it doesn't). Go figure.

OH GREAT LORDS OF JAVASCRIPT AND THE DOM, PRAY SHOW THE ERROR OF MY WAYS!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

By loading the script asynchronously, you are telling the browser that it can load that script independently of the other parts of the page. That means that the page may finish loading and may fire DOMContentLoaded BEFORE your script is loaded and before it registers for the event. If that happens, you will miss the event (it's already happened when you register for it).

In all modern browsers, you can test the document to see if it's already loaded (MDN doc), you can check:

if (document.readyState !== "loading")

to see if the document is already loaded. If it is, just do your business. If it's not, then install your event listener.

In fact, as a reference source and implementation idea, jQuery does this very same thing with it's .ready() method and it looks widely supported. jQuery has this code when .ready() is called that first checks to see if the document is already loaded. If so, it calls the ready function immediately rather than binding the event listener:

// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
    // Handle it asynchronously to allow scripts the opportunity to delay ready
    return setTimeout( jQuery.ready, 1 );
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...