スキップしてメイン コンテンツに移動

Google ChromeでDOMContentLoadedが発生しないケースがある

タイトルのとおり

Google Chromeは大変速いブラウザですが、その速さ故か、たまにDOMContentLoadedが発生しないケースがあります。
以下のようなコードで再現確認できます。

HTML
<!DOCTYPE HTML>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>domcontentloaded test</title>
</head>
<script type="text/javascript">
  (function(d){
   d.addEventListener('DOMContentLoaded', function(){ alert('nya-'); }, false );
   var s = d.createElement('script');
   s.src = 'hoge.js';
   s.charset="UTF-8";
   var h = d.getElementsByTagName('head')[0];
   h.insertBefore( s, h.firstChild );
   })(document);
</script>
<body>
  <h1>debug</h1> 
</body>
</html>

JavaScript(hoge.js)
document.addEventListener('DOMContentLoaded', function(){ alert('nya-2'); }, false );

解決策

window.onloadにイベントを割り当てましょう。
具体的には以下のコード
var isLoad = false;

document.addEventListener('DOMContentLoaded', function(){ isLoad = true; alert('nya-2'); }, false );

window.addEventListener('load', function(){ if( !isLoad ){ alert('nya-2'); } }, false );


最後に

この現象は、たまたま今日見つけたものです。
もしかしたら、僕の環境だけで発生するレア現象なのかもしれませんが、同様のケースで困った方がいらっしゃいましたら、何かの参考にして頂けたら幸いです。

コメント

  1. DOMContentLoadedが発生しないのではなく、後から追加したscript要素内でDOMContentLoadedに登録してもDOMContentLoadedの発生に間に合わないことがあるってことですよね。
    createElementして追加したscript要素の実行タイミングは保証されていないので、Chromeに限らず、DOMContentLoadedに間に合わない可能性はあります。(といいつつ、FirefoxとOperaの実装では実行タイミングを保証しています)。

    返信削除
  2. >os0xさん

    コメントありがとうございます。

    >DOMContentLoadedが発生しないのではなく、後から追加したscript要素内でDOMContentLoadedに登録してもDOMContentLoadedの発生に間に合わないことがあるってことですよね。

    って事です。
    難しいですね、日本語。

    返信削除
  3. とりあえず、hoge.js を以下のようにすると動作するようです。

    ---
    (function (loadedListener) {
     var doc, readyState;

     doc = document;
     readyState = doc.readyState;

     if (readyState === 'complete' || readyState === 'interactive') {
      loadedListener();
     } else {
      doc.addEventListener("DOMContentLoaded", loadedListener, false);
     }
    })(function () {
      alert('nya-2');
     });
    ---

    document.readyState === 'interactive' 以上が保証されれば、DOMContentLoaded 以降のタイミングのはずなので問題ないと思います。
    このままでは第一引数で event を受け取れないのがネックですが。

    返信削除
  4. >think49さん

    コメントありがとうございます。

    documentのreadyStateを使う方法は試したのですが、IE(憎き奴です)で上手く行かなかったので、諦めました。
    ただ、IEを無視するならば、その判定方法がスマートですね。

    返信削除

コメントを投稿

このブログの人気の投稿

Amazonの不正アクセス→注文履歴が表示されないという謎の現象

Amazon から身に覚えのない注文が飛んできた Amazonマーケットプレイス出品者「ngahuibaihuo」がお客様のご注文を承ったことをお知らせいたします。 というメッセージと共に全く身に覚えの無い注文が5点飛んできた。 値段は一つあたり11円と非常に低額であったが、これは不正アクセスだと判断。 すぐにアマゾンにログインしなおし、パスワードの変更を行った。 面倒臭がっていた2段階認証も設定した。 正直、かなり焦った。 この注文は、なぜか自動的に、「 非表示にした注文 」に変更されていた。 なので、注文履歴をぱっと見ただけでは、不正な注文があったと思われないようになっている。 非表示にした注文を表示する 注文履歴のページから、ドロップダウンリストを選び、一番下の「 非表示にした注文 」を選択する。 これで不正アクセスで注文された履歴が表示されるはず。 後は、それらの商品を選択してキャンセルすればOKだ。 残る謎 Amazonのパスワードは、自動生成で作成した難読系なので、そう簡単に不正アクセス出来るようなものでは無い。 しかしながら、2段階認証を設定していなかったのが、今回のような件を引き起こしてしまったのかもしれない。 注文の金額がやたらと低かったのも気になる。 11円の商品を3個とか2個とか購入していた。 この「ngahuibaihuo」というアカウントが被害にあった側なのか、むしろこいつが犯人なのかは全く分からないが、今回の手口はかなり凝ったやり方になっているので、似たような被害に合った方の参考になればと思っている。 良く分からない人は遠慮せずにAmazonのカスタマーセンターに電話して聞くのが一番だと思う。

ブラウザの拡張をつくろう!

いつもの前振り 初めましてもそうでない方もお元気ですか。 元気があれば何でも出来る!出来ません。 JavaScript Advent Calender 、13日目担当のArc Cosineです。 今回はJavaScriptのネタを何か書こうと思いましたが、どうせならツールの一つくらい作ったほうがいいだろうと言う事で土日に突貫工事で作ってみました。 Extension Maker http://www.tunsns.net/ExtensionMaker/ 時間切れで間に合いませんでしたが、Opera拡張だけは作れるようになっていますので、試してみてください。 チュートリアル トップヘアクセスしたら右下にある「今すぐ試してみる」をクリックしましょう。 そうしますと、基本情報を入力する画面が出ますので、必要な情報を入力してください。 今は入力チェックしていませんが、将来的にはちゃんとチェックするようにします。 次に、コードを入力する画面が出てきますので、ここにコードを貼り付けましょう。 Operaで動くUserScriptを試しに貼ってみると良いでしょう。 例えば、僕が昔書いたcolorful_favstarとかね! コード貼っておきますね。 コピペする場合は、view plainをクリックすると楽にコピペ出来ますよー。view plainの文字、薄くて見づらいけれど。 // ==UserScript== // @name Colorful Favstar.fm // @namespace http://moco.nond.es/ // @description Change tweet color and font size by favourites count like Favotter.net. // @version 0.1.1.20100808 // @include http://favstar.fm/* // @include http://ja.favstar.fm/* // @include http://de.favstar.fm/* // ==/UserScript== (function(doc){