jQueryでタイマーの実装
jQuery の Timer プラグイン を使ってカウントダウンタイマーを作ってみたいと思います。
プラグインの読み込み
まず始めに jQuery とダウンロードした jquery.timer.js を読み込みます。
jQuery は Google Ajax API を利用して読み込みます。
<!-- Google CDN の jQuery --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script> <!-- Timer plugin --> <script src="jquery.timer.js" type="text/javascript"></script>
Timer プラグインの使い方は簡単で、$.timer(インターバルミリ秒, 実行する関数) です。
$.timer(1000, function (timer) { alert("hello"); timer.stop(); });
setInterval の落とし穴
Javascript の setInterval 関数は実行のタイミングが直感とやや違っていて、
これについては 「JavaScript を学ぶ際に一番重要なのに、誤解されがちな setTimeout 系の概念」
こちらの記事に詳しく書かれています。
jQueryのTimerプラグインも中身は setInterval を使用しているので、同じ誤解がありそうです。
ためしに下のコードを実行してみると、結果は hoge piyo (1000msおいて) fuga の順番になりした。
$(function() { $( 'body' ).append( 'hoge<br />' ); //タイマーをセット $.timer(1000, function( timer ) { $( 'body' ).append( 'fuga<br />' ); timer.stop(); }); $( 'body' ).append( 'piyo<br />' ); });
Timer プラグインは timer.stop() をかけるまでインターバルをおいて、
関数を実行キューに登録し続けるといったものです。
なので timer.stop() をかけるタイミングを間違うと、
一回余計に関数が実行されてしまうといった類のバグがおこりそうです。
カウントダウンタイマーを作ってみる
<!DOCTYPE HTML> <html lang="ja"> <head> <meta charset="UTF-8"> <title>timerテスト</title> <!-- Google CDN の jQuery --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script> <!-- Timer plugin --> <script src="jquery.timer.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { //タイマー作動中のフラグ var timer_state = false; function timerStart() { $.timer(1000, function(timer) { if(timer_state == true){ var time = $( '#time' ).val(); time = ( ~~time - 1 ); if( ~~time > 0 && timer_state == true ) { $( '#time' ).val(time); } else { $( '#time' ).val('time out!'); timer.stop(); } } }); } $('#start').click(function(){ timer_state = true; timerStart(); }); $('#stop').click(function(){ timer_state = false; }); }); </script> </head> <body> <input id="time" type="text" /> <button id="start">start</button> <button id="stop">stop</button> </body> </html>
この実装でもタイマーとしては機能します。
しかし致命的なバグがあります。
それは stop → start のクリックが 1 秒以内にあると、
カウントダウンの関数が二重で実行キューに登録されてしまうのです。
こうなるとタイマーは1秒で2回実行されおかしな挙動となります。
まとめ
今回はタイマーの二重起動を解決するうまい方法が思いつかなかったので、
stop → start を1秒以内にクリックすることを禁止する関数を挟む
といった泥臭い方法でしのぎました。
なにかいい方法がありそうですけどね。
.
コメントを残す