2025.08.29
Laravelで空判定にif文を使うとハマる理由
2018.01.31
プログラミングsetIntervalとsetTimeoutの非同期プログラミング

Canadian Devです。今回はJavaScriptの非同期プログラミングのベイシックドリルに取り組んでみたいと思います。
タイプライターみたいに、文章をブラウザに1文字ずつ表示して、一つの文が終わったら1秒の隙間を開けてから次の文に進む。
JavaScriptのsetIntervalというファンクションを使うとすぐにできます。”Interval”という言葉は日本語で「間隔」という意味で、「一定の間隔を置いて」ファンクションを実行するときに使います。それで、setIntervalは二つの引数を受けるのです。1番目の引数が実行したいファンクションで、2番目の引数が間隔の長さを表す整数です。
var string = "Hello!";
var index = 0;
var characterSequence = setInterval(function() {
 $('div#terminal-screen').append(string[index]);
 index++;
 if (index >= string.length) clearInterval(characterSequence);
}, 50);
上記のファンクションによると、characterSequenceという変数にsetIntervalというファンクションが指定されます。そのファンクションの1番目の引数で実行したい内容を指定します。string[index]の文字をdiv#terminal-screenに表示してindexを増加するファンクションです。それに、stringの最後の文字になるとclearIntervalでファンクションを止める条件を付けます。例1を参考してください。
次に、”Hello!“だけではなく、いくつかの文が入った配列をsetIntervalで実行してみましょう。下記のコードはどうでしょうか?
var stringArray = ["Hello!", "How are you?", "Goodbye."];
stringArray.forEach(function(string) {
 var index = 0;
 var characterSequence = setInterval(function() {
  $('#terminal-screen').append(string[index]);
  index++;
  if (index >= string.length) clearInterval(characterSequence);
 }, 50);
})
最初のコードとほぼ一緒で、配列をループして繰り返すたびにsetIntervalを実行させます。でも、このコードを実行すると、アウトプットが”Hello! How are you? Goodbye.”ではなくて、”HHGeoolwol doab!ryee .you?”になってしまいます(例2)。それはJavaScriptの非同期動作のためです。setIntervalをループすると一回で実行することになります。その非同期のsetIntervalが次々と実行するようにどう処理すればいいでしょう?
この問題に解決法がいろいろあります。配列を一つのストリングに結合してもいいし、コールバックを使う処理もありです。でも、setTimeoutで処理したらどうですか?setTimeoutはファンクションの実行する時間を明白にします。setTimeoutは二つの引数を受けます。一つ目は相変わらず実行したいファンクションですが、二つ目はsetIntervalと違って、ファンクションが実行するのにどれぐらい遅延するかという時間設定です。setIntervalと違って、一回しか実行されません。ループの中にsetTimeoutを使うと、配列に入ったストリングが次々と出るようにできます。下記のコードを見てみましょう。
var stringArray = ["Hello!", "How are you?", "Goodbye."]
var timeDelay = 0;
stringArray.forEach(function(string) {
 var index = 0;
 setTimeout(function() {
  var characterSequence = setInterval(function() {
   $('#terminal-screen').append(string[index]);
   index++
   if (index >= string.length) clearInterval(characterSequence);
  }, 50);
 }, timeDelay);
 timeDelay += string.length*50 + 1000;
});
setTimeoutの1番目の引数は先のsetIntervalのファンクションで、2番目の引数はtimeDelayという遅延時間の変数になります。配列をループするたびにそのtimeDelayという変数にsetIntervalという時間と1秒の遅延時間が追加されます(string.length*50 + 1000)。つまり、最初に実行する時間を設定します(例3)。
setTimeoutとsetIntervalを使うと自分が好むタイミングでイベントを実行することができます。面白くて効果的なUIがたくさん作ることができるでしょう。どちらも便利で使いやすいファンクションですが、非同期動作のことで注意しましょう。
【記事への感想募集中!】
記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!【テクノデジタルではエンジニア/デザイナーを積極採用中です!】
下記項目に1つでも当てはまる方は是非、詳細ページへ!Qangaroo(カンガルー)
【テクノデジタルのインフラサービス】
当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。
最近の記事
1

2025.08.29
Laravelで空判定にif文を使うとハマる理由
2

2025.08.29
Git SSH接続でfetch/pullができなくなった時の対処法
3

2025.08.28
【体験談】Amazon Linux 2でMySQLインストール時のOpenSSL・GPG key エラーにハマった話
4
2025.08.28
【AWS】SSMポートフォワーディングとInstance Connectを利用したプライベートEC2へのSSH接続手順
5

2025.07.24
Log::info()が使えない!?Laravel.logのPermission denied エラーを解決する(Docker環境)
タグ検索