#023
posted on 2021.01.29 (Fri) 2023.01.30 (Mon)

JavaScriptをページ読み込みの任意のタイミングで実行。

ブラウザがサーバーからレスポンスを受け取ったあと、ページ読み込みが完了するまでの間のJavaScriptの実行タイミングの指定方法。忘れるのでメモ。

  1. DOMの解析の途中で任意に実行する。
  2. DOMの解析が完了(HTMLドキュメントの読み込みが完了)した時点で実行する。
  3. 画像などページのすべてのリソースデータの読み込みが完了した時点で実行する。
  4. ロードのステータス(readyState属性)が変化したときに実行する。
  5. DOMの解析とは非同期でjsファイルを読み込んで実行する。

 

 

DOMの解析の途中で実行

DOMの解析がスクリプトを記述した位置に達した時点で実行させる方法。

※ JavaScriptが実行されるとその処理が完了するまでDOM解析は一時停止するので、通常はDOM解析が完了してから実行させるか、非同期に実行する。

 

HTML内の任意の場所に実行処理を記述する。

  1. headタグ内に記述
    DOM読み込みの最初にスクリプト処理を実行したいとき。
  2. bodyタグ内の任意の場所に記述
    DOM読み込み途中の任意のタイミングでスクリプト処理を実行したいとき。
  3. body終了タグ直前に記述
    DOMを最後まで構築したタイミングでスクリプト処理を実行したいとき。
<!DOCTYPE html>
<html>
<head>
<!-- (1) headタグ内に記述 -->
</head>
<body>

<!-- (2) body内の任意の場所に記述 -->

<!-- (3) body終了タグ直前に記述 -->
</body>
</html>

 

 

DOMの解析が完了した時点で実行

HTMLドキュメントがすべて読み込まれ、DOMにアクセスする準備ができた時点で実行させる方法。

※ スタイルシートや画像などの副リソースの読み込みは待たない。

 

body終了タグの直前に記述するか、DOM解析完了時に発火する「DOMContentLoaded」イベントを使う。

 

1. ネイティブJavaScriptの場合

documentオブジェクトのaddEventListener()メソッドで「DOMContentLoaded」イベントを指定。

※ 「DOMContentLoaded」イベントはdocumentオブジェクトで発火してからwindowオブジェクトにバブリングするので、windowオブジェクトでも捕捉できる。(documentオブジェクトで先に発火するので、documentオブジェクトを指定するのが無難。)

document.addEventListener('DOMContentLoaded', function(){
   // 実行したい処理..
});

2. jQueryの場合

jQueryの場合は、ready()メソッドを使う。

//readyメソッドでの記述方法
$(document).ready(function(){
   // 実行したい処理..
});

//簡略化した記述方法
$(function(){
   // 実行したい処理..
});

 

 

すべてのデータの読み込みが完了した時点で実行

画像などページのすべてのリソースデータの読み込みが完了した時点で実行させる方法。

 

すべてのデータの読み込み完了時に発火する「load」イベントを使う。

 

1. ネイティブJavaScriptの場合

windowオブジェクトのaddEventListener()メソッドで「load」イベントを指定。

※ 副リソースのロードを捕捉する必要があるので、documentオブジェクトではなくwindowオブジェクトで実行する。

※ windowオブジェクトの「onload」プロパティーに代入しても同じタイミングで動作するが、「onload」プロパティーの場合は、複数の場所に記述があると最後に代入した記述内容ですべてが上書きされる。

window.addEventListener('load', function(){
   // 実行したい処理..
});

//上記と同じ動作(この記述方法の場合は、複数あると最後の代入ですべて上書きされる)
window.onload = function(){
   // 実行したい処理..
}

2. jQueryの場合

jQueryの場合は、on()メソッドで「load」イベントを指定。

$(window).on('load', function(){
   // 実行したい処理..
});

 

 

ロードのステータスが変化したら実行

ページロードのステータス(readyState属性)が変化するときに実行させる方法。

 

ステータスは下記の順番で変化する。

  1. 「loading」: DOMの解析中。
  2. 「interactive」 : DOMの解析が済み、画像など副リソースの読み込み中。(DOMContentLoadedイベントより前に発火。)
  3. 「complete」 : 副リソースの読み込が完了。(loadイベントより前に発火。)

※ 現在のステータスの値は、documentオブジェクトの「readyState」プロパティーで参照できる。(「document.readyState」)

 

1. ネイティブJavaScriptの場合

documentオブジェクトのaddEventListener()メソッドで「readystatechange」イベントを指定。

※ 「readystatechange」イベントの発火は、ステータスが「interactive」と「complete」に変化するときの2回。

document.addEventListener('readystatechange', function(){
   // 実行したい処理..

   // interactiveに変化したときだけ実行
   if(document.readyState === 'interactive'){
      // 実行したい処理..
   }

   // completeに変化したときだけ実行
   if(document.readyState === 'complete'){
      // 実行したい処理..
   }
});

2. jQueryの場合

jQueryの場合は、on()メソッドで「readystatechange」イベントを指定。

$(document).on('readystatechange', function(){
   // 実行したい処理..

   // interactiveに変化したときだけ実行
   if(document.readyState === 'interactive'){
      // 実行したい処理..
   }

   // completeに変化したときだけ実行
   if(document.readyState === 'complete'){
      // 実行したい処理..
   }
});

 

 

非同期でjsファイルを読み込み、実行

jsファイルのリソース読み込みをDOMの解析とは非同期にすることで、DOMの構築を止めることなく、バックグラウンドで並走して読み込んだスクリプトを実行させる方法。

 

1. JavaScriptで<script>要素を生成して読み込む方法

  1. JavaScriptでHTMLの<script>要素を動的に生成。
  2. 「src」属性に「読み込みたいjsファイルのパス」を設定。
  3. 生成した<script>要素をDOM内の任意の場所に挿入。(挿入先の要素までのDOM解析は完了している必要がある。)

※ 読み込んだjsファイルの処理のタイミングは保証されない。(ファイル読み込みが完了したら即実行される。)

※ 読み込んだjsファイル内の処理で「DOMContentLoaded」イベントを受け取れない。

※ この方法で読み込むjsファイル内にDOMのHTML要素や他の読み込みファイルに依存する処理がある場合、処理の精度を保つには何らかの対処が必要。(何かの要素などにアクセスが必要な場合は、setInterval()メソッドで指定の要素が存在するか定期的に確認して、確認できるまで待機するなど。)

//script要素を作成
const ag2script = document.createElement('script');
//src属性の値に読み込みたいjsファイルのパスを代入
ag2script.src = 'ファイル名.js';
//作成したscript要素をhead要素にappendする
document.getElementsByTagName('head')[0].appendChild(ag2script);

[ jsファイルの非同期読み込み完了時に任意の処理を実行する方法 ]

生成した<script>要素によるjsファイルの読み込みが完了したら何かの処理をしたい場合は「load」イベントを使う。

※ jsファイルの読み取りに失敗したときに処理が必要な場合は「error」イベント(または「onerror」プロパティー)を使う。

ag2script.addEventListener('load', function(){
   // 実行したい処理..
};

//上記と同じ動作(この記述方法の場合は、複数あると最後の代入ですべて上書きされる)
ag2script.onload = function(){
   // 実行したい処理..
}

[ Promiseで実装する方法 ]

Promiseオブジェクトを使って、上記の処理を関数化して実装する方法。(PromiseはIE非対応。)

※ 下記では、「jsファイルのパス」と「挿入先の要素タグ」(デフォルトは<head>要素)を指定してjsファイルを動的に読み込めるように関数化。

※ Promiseオブジェクトのthen()メソッドは、処理がresolve(解決)されたときに第1引数の関数、reject(拒否)されたときに第2引数の関数を実行する。(第2引数は省略可能。)

//Promiseオブジェクトを使って処理を関数化
const ag2scriptPromise = function(src,tag='head'){
  return new Promise(function(resolve,reject){
    let ag2script = document.createElement('script');
    ag2script.src = src;
    document.getElementsByTagName(tag)[0].appendChild(ag2script);

    ag2script.addEventListener('load', function(){
      resolve('Loaded: "'+ag2script.src+'"');
    });
    ag2script.addEventListener('error', function(){
      reject(new Error('Loading Error: "'+ag2script.src+'"'));
    });
  });
};

//読み込みたいjsファイルを指定して関数を実行
ag2scriptPromise('ファイル名.js').then(function(resolve){
  console.log(resolve);
  // 読み込み完了時に実行したい処理..
},function(error){
  console.log(error.message);
  // 読み込み失敗時に実行したい処理..
});

 

2. <script>タグの属性で指定する方法

jsファイルを読み込む<script>要素タグに、「defer」属性または「async」属性を記述する。

※ jsファイルを外部読み込みしている場合のみ有効なので、「src」属性が無い<script>タグでは無視される。

※ <script>タグの記述順でjsファイルで実行したい場合は「defer」属性、読み込みが完了したjsファイルから順に即実行したい場合は「async」属性を使う。(どちらもファイルの読み込みは非同期に行われる。)

<script src="ファイル名.js" defer></script>
<script src="ファイル名.js" async></script>

defer属性 : DOMの解析を中断せず非同期でjsファイルを読み込むが、DOMの解析完了後(かつ「DOMContentLoaded」イベントの発生前)にスクリプトの処理を実行する。<script>タグの記述順でjsファイルの処理を実行していく。

async属性 : DOM構築とは関係無く非同期でjsファイルを読み込み、<script>タグの記述順ではなく、読み込みが完了したjsファイルから順次処理を実行する。

 

 

この記事のURL

https://memo.ag2works.tokyo/post-1199/

Copyコピー
この記事のタイトル

JavaScriptをページ読み込みの任意のタイミングで実行。 | memo メモ [AG2WORKS]

Copyコピー
この記事のリンクタグ

<a href="https://memo.ag2works.tokyo/post-1199/" target="_blank" rel="noopener">JavaScriptをページ読み込みの任意のタイミングで実行。 | memo メモ [AG2WORKS]</a>

Copyコピー
※ フィールドをクリックでコピーするテキストの編集ができます。

この記事へのコメント

コメントの書き込みはまだありません。

  • コメント内のタグはエスケープ処理され、文字列として出力されます。
  • セキュリティーのため、投稿者のIPアドレスは取得されます。
  • 管理者が内容を不適切と判断したコメントは削除されます。
  • このフォームにはスパム対策として、Googleの提供するreCAPTCHAシステムが導入されています。
    (Google Privacy Policy and Terms of Service.)