実現イメージ
Webページの読み込みが完了した時点でJavaScriptを実行したいため、readyStateとDOMContentLoadedを使って制御を行おうと考えた。
当初のコード
if (document.readyState === "complete") {
// ページの読み込みが完了している場合、直ちに関数を実行
this.send();
} else {
// そうでない場合、DOMContentLoadedで関数を実行
document.addEventListener("DOMContentLoaded", () => {
this.send();
});
}
readyStateがcompleteだったら即実行して、そうでなければDOMContentLoadedイベントで発火する仕掛けにした。
動かない時がある
しかし、実際にこれをWebサイトに埋め込んでみると埋め込んだページによっては処理が発火しないケースがあった。
そこで、ブレイクポイントを仕込んでreadyStateを確認してみたところ、
上記のようにreadyStateがinteractiveになっていた。
そのため、DOMContentLoadedで発火する分岐に入っているのだが、
readystateの各ステータスとDOMContentLoadedの発生順は、
- loading: ドキュメントが読み込み中。
- interactive: ドキュメントが完全に読み込まれているが、サブリソース(画像など)がまだ読み込まれていない。この時点でDOMContentLoadedイベントが発火します。
- complete: ドキュメントとすべてのサブリソースが読み込まれた。この時点で load イベントが発火します。
となるため、interactiveを確認した時点でDOMContentLoadedを設定しても時すでに遅し、ということでした。
修正後のコード
if (document.readyState === 'loading') {
// 読み込み中ならDOMContentLoadedで関数を実行
document.addEventListener('DOMContentLoaded', () => {
this.send();
});
} else {
// そうでなければ即実行
this.send();
}
loadingの時だけDOMContentLoadedイベントで発火させて、それ以外は即実行するようにしました。
これにより問題が無事解決しました。
まとめ
Webページの読み込み状態に応じてJavaScriptの実行タイミングを制御することは、多くのWebサイトやアプリケーションで重要です。この記事では、readyStateとDOMContentLoadedを使用して、その制御を試みた経緯と、遭遇した問題、そしてその解決策について詳しく説明しました。
初めはreadyStateがcompleteの場合にのみ即時実行するアプローチを採用しましたが、interactiveの状態での動作を考慮していなかったため、問題が発生しました。最終的には、loadingの時だけDOMContentLoadedイベントで処理を実行し、それ以外の場合は即時実行する方法に変更し、問題を解決しました。
この経験を通じて、Web開発においては、各ブラウザや状態における動作の違いを理解し、それに対応する方法を考えることの重要性を再認識しました。読者の皆様も、この記事が同様の問題に直面した際の参考となれば幸いです。