2012-02-11 6 views
22

私はDOMContentLoadedを持つ非同期ロードされたスクリプト、またはロードされているイベントハンドラが呼び出されていないか?

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

asynchronously-ロードしていますhandler-

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

がしかし、イベントハンドラと呼ばれることはありませんDOMContentLoadedイベントにスクリプトを持っています。同期してロードする場合 -

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

正常に動作します。

(私はloadイベントにDOMContentLoadedイベントを変更しても、それが呼び出されることはありませんです。)

できますか?イベントハンドラは、スクリプトがブラウザによってどのようにロードされるかにかかわらず登録されるべきですか?

編集:それはクローム18.0.1025.11ベータ版では動作しませんが、DOMContentLoadedと、それは、Firefox 11ベータ版にを行います(ただし、loadとそうでありません)。 Go figure。 JavaScriptとDOMの

OH GREAT LORDSは、PRAY MY WAYS OF ERRORを表示します!

+1

非同期でスクリプトをロードすることにより、あなたはそれがページの他の部分から独立してそのスクリプトを読み込むことができ、ブラウザを語っています。これは、ページが読み込みを終了し、スクリプトがロードされる前とイベントの登録前にDOMContentLoadedが発生する可能性があることを意味します。それが起これば、あなたはイベントを逃すでしょう(あなたがそれを登録するときにはすでに起こっています)。 – jfriend00

+0

ああinteredasting。だから私はすでにイベントをテストしているはずです - ** ** edit **:実際には、スクリプトの後にイベントを発生させるので、非同期ではありません。クール。答えとして書くとアップヴォートを持つことができます:) – user1203233

答えて

46

非同期スクリプトを読み込むことで、あなたはそれが独立したページの他の部分のスクリプトを読み込むことができ、ブラウザを語っています。つまり、ページが読み込みを完了し、スクリプトがロードされ、イベントに登録される前にDOMContentLoadedが発生する可能性があります。それが起これば、あなたはイベントを逃すでしょう(あなたがそれを登録するときにはすでに起こっています)。

は、一部のブラウザでは、あなたはそれがすでにロードされていますかどうかを確認するためにドキュメントをテストすることができます。私はすべてのブラウザの互換性をチェックしていないが、Firefoxでは3.6以降(MDN doc)、次のことが確認できます。文書がすでにロードされている場合

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

を参照してください。そうであれば、あなたのビジネスをしてください。そうでない場合は、イベントリスナーをインストールしてください。実際に

は、参照元と実装のアイデアとして、jQueryのは、それが.ready()方法だと、この非常に同じことをして、それが広くサポートされているに見えます。 .ready()が呼び出されたときにjQueryがこのコードを取得すると、最初に文書が読み込まれているかどうかがチェックされます。これが最終的な答えではない

// 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); 
} 
+0

はい、それは私が知る必要があったすべてです。私はupvote-haven'tが十分な担当者を持っていることに嘘をついた;)私は誰かがあなたのためにこれをアップ - 投票するために十分親切であることを願って:) – user1203233

+0

'document.readyState'がGecko-onlyの場合: 'DOMContentLoaded'イベントハンドラ* synchronously *実行時にグローバルフラグを設定します。これは後で確認できます:) **編集**:クールなブラウザがすべてサポートされているので大丈夫です – user1203233

+7

試してみると、 'document.readyState == 'complete''のチェックは十分ではありません* - チェックが行われたとき、' document.readyState'は 'interactive'でした。 'document.readyState!= 'loading''のチェックはうまくいきます:) – user1203233

17

が、DOMを変更する必要があるスクリプトを使って非同期を使用して修正し、そうしなければなりませんされていない理由を私は理解して作られた:もしそうなら、それはイベントリスナーをバインドすぐにではなく、準備ができて関数を呼び出しますDOMContentLoadedイベントまで待機します。希望は有益かもしれません。

enter image description here

(出典:Running Your Code at the Right Time from kirupa.com)この周り

2

一つの方法は、windowオブジェクトにロードイベントを使用することです。

これはDOMContentLoadedよりも遅く発生しますが、少なくともイベントがないことを心配する必要はありません。

window.addEventListener("load", function() { 
    console.log('window loaded'); 
}); 

本当にDOMContentLoadedイベントをキャッチする必要がある場合は、Promiseオブジェクトを使用できます。約束は、それ以前に起こった場合でも解決されます:

HTMLDocument.prototype.ready = new Promise(function (resolve) { 
if (document.readyState != "loading") 
    return resolve(); 
else 
    document.addEventListener("DOMContentLoaded", function() { 
     return resolve(); 
    }); 
}); 

document.ready.then(function() { 
    console.log("document ready"); 
}); 
関連する問題