目にも留まらぬ早業
動きが速すぎて何が起きたのか判らないときがあります。映像の世界ではスローモーションビデオによる再生で動作をゆっくり見せています。プログラミングではwait, sleep, delay等の関数が用意されているのでゆったりした表現を支援しています。
そのあたりは『同期的な表現』で取り上げました。今回、再帰処理(recursive processing)で遅延するにはどのように制御するのか少し戸惑いましたので、確認した一例を記録に残します。
再帰処理(recursive processing)
再帰関数(recursive function)の代表例に階乗(factorial)関数があります。関数の最後でディレー時間を設けるに当たりどこにディレー処理を用意すればよいのか悩みました。
求める階乗の値に関わらず一律に同じ待機時間に設定するにはそう簡単ではありません。待機時間を設置するには、setTimeout, setInterval, Promise, async/awaitなどがありますが、ここではasync/awaitを使っています。
async/awaitはPromise関数の標準的な使い方を短かい記述で可能にした表現方法のようです。
次のような使い方でC言語のsleep関数相当の機能を実現できます。非同期処理はasyncをつけた関数内でawaitをつけて実行させます。
階乗を求めるrecursiveな関数factorial()はmyPromise()のスコープ内に定義されていますが、必ずしもスコープ内に置く必要はありません。実質的にawaitをつけた関数で実行されれば期待した動作になります。
動作例
1~6の階乗を1秒間隔で表示します。ブラウザの再ロードボタンにて何度でも実行できます。
myAsync is starting.
再帰の基本➡うさぎでもわかる再帰関数のいろは
ディレーを実現する関数のサンプルコード
<html> <script type="text/javascript" charset="utf-8"> const CRLF="<BR>"; myAsync(); async function myAsync(){ //非同期関数を定義する際にasyncをつけて宣言する for(var i=1; i<=6; ++i){ var result = await myPromise(i); //実行結果を待つためにawaitをつけて実行 if(i==1) document.write("myAsync is starting."+CRLF); document.write(i+"!= "+result+CRLF);// 1 2 6 24 120 720 } } function myPromise(num){ //delay 1秒 return new Promise(function(resolve) { setTimeout(function() { resolve(factorial(num)) }, 1000) }); function factorial(n) { //階乗を求めるrecursiveな関数 if(n<=1) return 1; else return n * factorial(n - 1); } } </script> </html>