MENU

JavaScript関数・メソッドタイマー処理

【JavaScript】 タイマー処理/setTimeoutとsetInterval

更新日:2021/08/19

 

プログラムコードを作成していると、特定の時間経過後に処理を実行したいことがあります。
JavaScriptではsetTimeoutとsetIntervalで実現できます。

 

この記事ではsetTimeoutとsetIntervalの使用方法および、知っておくべき注意点をお伝えします。

 

重要:JavaScriptのタイマー処理

 

setTimeoutとsetIntervalは指定した時間が経過した後に、指定した関数を実行する関数です。
例えば5秒経過後に何らかの処理をおこないたい場合などに、使用します。

 

ただし、正確に5秒後に実行されるわけではありません。

 

もし何らかのコードを正確に5秒後に実行したい場合、メインとなるコードの処理と同時に、時間経過を監視する処理を実行する必要があります。

 

しかしJavaScriptはシングルスレッドで動作しているため、複数の処理を同時に実行することができません。

 

そのためまずは、setTimeoutまたはsetIntervalメソッドを実行して、”タイマー待ちである”ということをイベントの待機一覧に登録します。

 

イベントの待機一覧に登録

 

メソッド実行後は、その後に続くコードが順番に実行されます。

 

残りのコードを実行

 

一連のコード処理が終了すると、イベントループに入ります。
イベントループはイベントが発生してるのかを確認し、発生していたら対応するコールバック関数を呼び出します。

 

そして指定した時間が経過しているのが確認できたら、setTimeoutメソッドなどで登録したコールバック関数が呼び出されます。

 

イベントループ

 

 

 

このとき、次のようなことが考えられます。

 

●setTimeoutを呼び出した後、残りのコード終了まで5秒以上かかる。

 

●clickイベントなど他のイベント実行中に、5秒以上経過してしまう。

 

●イベントループ内で他のイベント発生確認中に、5秒以上経過してしまう。

 

様々な要因で、経過時間を確認した時点では5秒以上経過していることがほとんどです。

 

そのためJavaScriptのタイマー処理は、正確な時間で呼び出されることを前提として設計してはいけないことに注意してください。

setTimeout:時間経過後1回だけ実行

 

一定時間経過後に処理を行いたいときは、setTimeoutメソッドを使用します。

 

構文

 

setTimeoutメソッドの構文

 

setTimeout( コールバック関数 );
setTimeout( コールバック関数 , ミリ秒 );
setTimeout( コールバック関数 , ミリ秒 , 引数1 , 引数2 ... );

 

 

引数

 

■コールバック関数

 

一定時間経過後に、JavaScriptのシステムによって呼び出される関数です。
システムから引き渡される引数はありませんが、setTimeoutメソッド呼び出し時に独自の値を指定することができます。

 

■ミリ秒

 

コールバック関数が呼び出されるまでの時間をミリ秒で指定します。

 

省略可能です。
省略された場合は0が指定されたとみなされます。

 

値は0から指定できますが、処理系によっては呼び出しまでの最短時間が制限されることがあります。
例えばブラウザ上で動作するJavaScriptの多くは4ms以上に制限されています。
またブラウザの非アクティブなタブ上での呼び出しは、1秒以上に制限されています。

 

■引数1 , 引数2 ...

 

省略可能です。
システムによるコールバック関数呼び出し時に、引数として渡されます。

 

戻り値

 

setTimeoutメソッドで登録されたタイマーイベントを識別するためのデータが返ります。
タイマーを停止させるために使用します。

 

この値は処理系により異なります。

 

例:
ブラウザ ... 整数値
node.js ... オブジェクト

 

使用例

 

一定時間経過後に処理をおこなう

 

次のコードは3秒後に経過時間を表示しています。

 

使用例1:3秒後に経過時間を表示

 


 const startTime = Date.now();

 setTimeout( function (){
     console.log( Date.now() - startTime );  // 3008
 },3000);

 

Date.now()を使用することで、経過時間を計測することができます。
詳しくは次の記事を読んでみてください。
【JavaScript】 経過時間や日数を取得し処理時間などを計測

 

一定時間ごとに処理をおこなう

 

次の処理は、コールバック関数内でsetTimeoutを呼び出すことで3秒毎に同じ処理をおこなっています。

 

3秒毎に処理をおこなう

 


const timeoutFunc = ()=>{
 console.log( Date.now() - startTime );
 setTimeout( timeoutFunc , 3000 );
};
const startTime = Date.now();

setTimeout( timeoutFunc , 3000 );

 

ここでの注意点は、setTimeoutメソッドを実行した時点が時間計測の開始位置となることです。
コールバック関数内でsetTimeoutメソッド以前の処理が何秒かかっても、関係ありません。

 

setTimeout実行後から計測

 

この後に紹介するsetIntervalは一定時間毎に繰り返し処理をおこなうメソッドですが、コールバック関数の開始が次のタイマー呼び出しの計測開始位置となります。

 

上のコードはtimeoutFunc関数内でtimeoutFunc関数を呼び出しているように見えます。
そのため再帰処理と混同することがあります。

 

実際にはsetTimeoutメソッドでtimeoutFunc関数をイベントキューに登録しているだけです。
timeoutFunc関数の呼び出しは、イベントループでおこなわれるので再帰ではありません。

 

 

 

setInterval:指定時間毎に繰り返し実行

 

一定時間毎に処理を繰り返したいときは、setIntervalメソッドを使用します。

 

構文

 

setIntervalメソッドの構文

 

setInterval( コールバック関数 , ミリ秒 );
setInterval( コールバック関数 , ミリ秒 , 引数1 , 引数2 ... );

 

 

引数

 

■コールバック関数

 

一定時間経過後に、JavaScriptのシステムによって呼び出される関数です。
システムから引き渡される引数はありませんが、setIntervalメソッド呼び出し時に独自の値を指定することができます。

 

■ミリ秒

 

コールバック関数が呼び出されるまでの時間をミリ秒で指定します。

 

値は0から指定できますが、処理系によっては呼び出しまでの最短時間が制限されることがあります。
例えばブラウザ上で動作するJavaScriptの多くは10ms以上に制限されています。
またブラウザの非アクティブなタブ上での呼び出しは、1秒以上に制限されています。

 

■引数1 , 引数2 ...

 

省略可能です。
システムによるコールバック関数呼び出し時に、引数として渡されます。

 

戻り値

 

setTimeoutメソッドで登録されたタイマーイベントを識別するためのデータが返ります。
タイマーを停止させるために使用します。

 

この値は処理系により異なります。

 

例:
ブラウザ ... 整数値
node.js ... オブジェクト

 

使用例

 

次のコードは3秒毎に経過時間を表示しています。

 

使用例1:3秒後に経過時間を表示

 


const startTime = Date.now();

setInterval( function (){
 console.log( Date.now() - startTime );
},3000);

// 実行結果
// 3004
// 6016
// 9030
// 12044
// ・・・・

 

setIntervalはコールバック関数の開始が次のタイマー呼び出しの計測開始位置となります。
そのため、コールバック関数の処理時間が指定時間以上かかる場合、イベントループに入った時点で次のコールバック関数呼び出しがおこなわれます。

 

コールバック関数呼び出しの間隔をあけたい場合は、setIntervalではなくsetTimeoutメソッドを連続して呼び出してください。

 

 

clearTimeout/clearInterval:タイマーを中止する

 

setTimeoutまたはsetIntervalメソッドで登録したタイマーを中止するときは、clearTimeoutまたはclearIntervalメソッドを使用します。

 

構文

 

 

 

clearTimeoutおよびclearIntervalメソッドの構文

 

clearTimeout( タイマーID );
clearInterval( タイマーID );

 

 

引数

 

■タイマーID

 

setTimeoutまたはsetIntervalメソッドが返した値です。

 

setTimeoutが返したIDはclearTimeoutで、setInterval返したIDはclearIntervalで使用することが想定されますが、処理系によっては逆の組み合わせでもタイマーを停止することができます。

 

しかし想定通りの組み合わせで使用することを推奨します。

 

 

使用例

 

setIntervalの停止

 

setIntervalで登録したタイマーを、コールバック関数を5回呼び出した時点で停止させる例です。

 

setIntervalの停止

 


const startTime = Date.now();
let count = 0;

const timerID = setInterval( function (){
    console.log( Date.now() - startTime );
    if( ++count >= 5 ) clearInterval(timerID);
},3000);

 

setTimeoutの停止

 

setTimeoutで登録したタイマーが、コールバック関数を5回呼び出した時点で停止する例です。

 

setIntervalの停止

 


const timeoutFunc = count =>{
   console.log( Date.now() - startTime );
   count ++;
   const timerId = setTimeout( timeoutFunc , 3000 , count);
   if( count >= 5 ) clearTimeout(timerId);
};
const startTime = Date.now();

setTimeout( timeoutFunc , 3000 , 0);

 

上のコードでは呼び出しカウントをコールバック関数の引数として渡しています。
外部でカウント用の変数を用意するよりも、スマートですね。
場合によっては、startTimeも引数で渡すかどうか検討する余地があります。

 

なお上のコードは、ムダな処理をおこなっています。

 

setTimeoutの後にclearTimeoutを実行していますが、setTimeoutを実行しなければいいだけですね。

 

修正:setIntervalの停止

 


const timeoutFunc = count =>{
    console.log( Date.now() - startTime );
    if( ++count < 5 ) setTimeout( timeoutFunc , 3000 , count);
};
const startTime = Date.now();

setTimeout( timeoutFunc , 3000 , 0);

 

setTimeout/setIntervalが効かないときの確認点

 

今回の記事を書くにあたってタイマーについて調査をおこなっていたら、タイマーが効かなくて困っている初心者がいることがわかりました。
setTimeoutとsetIntervalは重要:JavaScriptのタイマー処理でお伝えしていますが、イベントの待機一覧に”呼び出し時間””コールバック関数”を登録しています。

 

この二つを上手く引数として渡すことができていれば、イベントループでタイマー呼び出しが行われます。

 

何が問題なのか

 

”呼び出し時間”が問題?

 

”呼び出し時間”については数値を指定すればいいので問題ないと思います。
仮に"3000"などの数値文字列を指定しても、内部で数値に変換してくれます。
また"abc"などの数値ではない文字列は、0として扱われるようです。

 

どちらにしても、コールバック関数の呼び出しがおこなわれます。
”呼び出し時間”の設定値は問題ではありません。

 

”コールバック関数”が問題?

 

問題は”コールバック関数”です。

 

タイマー呼び出しが効かないというケースは、次のコードの(2)のように関数に()を付けていることが多いようです。

 


const timerFunc = ()=>{
    // 何らかの処理
};
setTimeout( timeoutFunc , 3000 );    //  (1)
setTimeout( timeoutFunc() , 3000 );   //  (2) タイマーが効かない!

 

(1)は、timerFunc変数が参照している関数オブジェクトを引数として渡しています。
渡された側は、()を付けることで関数を実行できます。

 

(2)はtimerFunc変数が参照している関数オブジェクトを実行して、その結果をsetTimeoutに渡しています。
実行した関数はreturn文がないので、結果はundefined値です。
undefined値は関数オブジェクトではないので、( )をつけても実行できません。
タイマーが効かないのは、これが理由です。

 

僕が初心者の頃同じ間違いをしていました。
その時の反省点を踏まえて、次のような記事を書いています。
【JavaScript】 コールバックに関数を指定すると実行されてしまう理由

 

無限ループするsetTimeout

 

次のコードは、この記事内で紹介しているsetTimeoutでタイマー呼び出しを連続しておこなうコードを変更したものです。

 


const timeoutFunc = ()=>{
 console.log( Date.now() - startTime );
 setTimeout( timeoutFunc() , 3000 ); // timeoutFunc → timeoutFunc()
};
const startTime = Date.now();
 
setTimeout( timeoutFunc() , 3000 ); // timeoutFunc → timeoutFunc()

 

timeoutFuncに( )がついているため、その場で関数が実行されます。
実行された関数内でも同様に関数が実行されます。

 

元のコードで「再帰呼び出しではない」と書いていますが、こちらのコードは再帰呼び出しになっています。
停止させる仕組みがないため、無限ループになります。

 

けーちゃんおススメJavaScript入門書

  • スラスラ読める JavaScript ふりがなプログラミング
  • プログラム未経験者がJavaScript始めるならコレ!
    コードを掲載して自分で理解しろという投げっぱなしな入門書とは異なり、コードに一つ一つどんなことをやっているかをふりがなという形式で解説しています。
    それでいてJavaScriptの基礎と応用を学べる良書です。
  • これからWebをはじめる人のHTML&CSS、JavaScriptのきほんのきほん
  • JavaScriptの機能を実践で活かすにはHTMLやCSSの知識が不可欠です。
    しかしそれらの知識があることが前提として書かれている書籍が多い中、この本は総合的な知識を身に着けることができます。
    HTMLやCSSの知識も不安な方には、ぴったりの一冊です
  •  

    入門書の役割は、自分のやりたいことをネットで調べることができるようになるための、基礎的な知識の獲得です。
    まずはこれらの本でしっかりと基礎知識を身につけましょう。
    そしてもっと高度なことや専門的なことはネットで調べ、情報が足りないと感じたら書籍を購入してください。


    記事の内容について

     

    こんにちはけーちゃんです。
    説明するのって難しいですね。


    「なんか言ってることおかしくない?」
    たぶん、こんなご意見あると思います。

    裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

    そんなときは、ご意見もらえたら嬉しいです。

    ご意見はこちら。
    https://note.affi-sapo-sv.com/info.php

    【お願い】

    お願い

    ■このページのURL


    ■このページのタイトル


    ■リンクタグ


    ※リンクして頂いた方でご希望者には貴サイトの紹介記事を作成してリンクを設置します。
    サイト上部の問い合わせよりご連絡ください。
    ただしサイトのジャンルによっては、お断りさせていただくことがあります。