警告
この取説は現状の FOT.task の仕様に基づくものです。
今後 FOT.task の仕様が変更される可能性があります。
引数で渡した関数を setTimeout で実行します。
// task.jsを読み込んで、FOT.task() を使えるようにしておきます。
// ※ 変数 FOT 以外の名前空間への汚染はありません。
function xxx_a(){ }
function xxx_b(){ }
// setTimeout(xxx_a, 300) を実行し、xxx_a() の終了後に setTimeout(xxx_b, 200) を実行
FOT.task([
{ exec : xxx_a, wait : 300 },
{ exec : xxx_b, wait : 200 },
]);
全ての機能は FOT.task で実行可能です。
他の関数は引数の形式が違うだけの構文糖です。
引数で指定した関数を順番に setTimeout で実行します。
FOT.task( array execute_list );
execute_list:実行する関数を含むオブジェクトの配列。
引数の配列の各要素は exec、wait、cnt を持つオブジェクトです。
execute_list[0] = { exec : function execute [, wait : number wait = 0 ] [, cnt : number cnt = 1 ] };
wait に -1 を指定した場合、その関数の setTimeout を実行するタイミングで
document.readyState == "loading" であれば、実行せずに待機します。
その後、document.readyState が "interactive" 以降になったタイミングで setTimeout を実行します。
実行するタイミングで既に "interactive" 以降だった場合、wait : 0 として実行します。
cnt に 1 以上を指定した場合、その関数を指定回数だけ setTimeout で繰り返し実行します。
cnt に -1 を指定した場合、その関数の戻り値が真の場合は、次もその関数を setTimeout で実行します。
戻り値が偽の場合は、次に指定されていた関数を setTimeout で実行します。
注意:0 を指定しても0回実行にはなりません。省略した場合と同じく、1回実行になります。
FOT.task.exec( function execute [, number wait = 0 ] );
関数を setTimeout で1回実行します。
FOT.task([{ exec : execute, wait : wait }]) と同じです。
FOT.task.ready( function execute );
関数を setTimeout で1回実行します。document.readyState == "loading" であれば、変わるまで待機したあと実行します。
FOT.task([{ exec : execute, wait : -1 }]) と同じです。
FOT.task.loop( function execute, number cnt [, number wait = 0 ] );
関数を setTimeout で cnt 回実行します。
FOT.task([{ exec : execute, wait : wait, cnt : cnt }]) と同じです。
FOT.task.while( function execute [, number wait = 0 ] );
関数の戻り値が真である限り、関数を setTimeout で繰り返し実行します。
FOT.task([{ exec : execute, wait : wait, cnt : -1 }]) と同じです。
このライブラリを使用する際に留意しておくべき事柄など。
一切やっていません。このマニュアルに明記されている以外の引数を渡せば、エラーが発生したり、想定外の動作をすることになります。
たとえば exec を省略したり関数以外を渡せばエラーになりますし、cnt に整数以外を渡せば無限ループします。
止まってはいけないプログラムで利用するのであれば、自分で try-catch するなり、引数と戻り値を完全にチェックするなりしてください。
最も適切な対応として、大切なプログラムでは、このライブラリを利用しないことをオススメします。
何やってるか知りたい人なら、見れば分かる程度には単純なはずです。
やってることはただのマトリョーシカ。「引数の関数を実行した後に次の関数を setTimeout に投げる」関数を作って、 それを順番に入れ子にしていって、一番最初の関数を setTimeout に投げる。それだけ。
元々の作成理由は document.readyState を待つ処理の定型化です。
FOT.task([
{ exec : initVariables }, // 前処理1
{ exec : createNode }, // 前処理2
{ exec : appStart, wait : -1 }, // 実行開始
]);
最初の関数を setTimeout で実行し、終了後すぐに次の関数を setTimeout で実行して、
2つ目の関数が終了した時点で document.readyState が "loading" であれば、
変わるのを待ってから3つ目を setTimeout で実行します。
実行順の保証と document.readyState の監視が目的だったので、setTimeout に渡すミリ秒の引数は単なるついで。
前の2つを分割することにあまり意味はありませんが、
一応、setTimeout に投げておいていったん処理を終了することで、
ブラウザが処理を受け付けるタイミングができるという効果があります。
銀行のATM行列と同じで、1つのプログラムが複数の処理を連続して実行すると、いつまでも占有が続きますが、
このように処理を切ることで、いわば処理ごとにATM行列に並び直すような状態になります。
ブラウザはこのタイミングで画面の描画やマウス・キーボードの入力を受け付けることができるので、
1つのプログラムが占有を続けてしまっていることで画面がロックしたままという状況を避けられます。
で、このライブラリを作ったことで長時間の処理によるロックの回避を覚えたので、 万年カレンダーではそれを利用しています。
function createCalendar()
{
let div = itf_view.cal;
div.fotSetEvent("click", elClickCalendar);
let time = state.time.clone();
let ce_cnt = calc_gc_month();
let clip = FOT.elm.createClip();
let count = 0;
let start = Date.now();
state.now = start;
if (loop())
{
FOT.task.while(loop);
}
function loop()
{
if (state.now != start){ return; }
clip.push("hr");
for (let m = 1; m <= 12; m++){ clip.push(createCalTable(time, (ce_cnt++) ? null : {})); }
div.push(clip);
itf_view.loop_year.textContent = ++count;
if (count < state.loop){ return true; }
div.push("hr");
itf_view.exec_time.textContent = " ( " + ((Date.now() - start) / 1000) + " 秒)";
}
}
関数 loop() はカレンダー1年分(12か月)の表示です。最初の1年だけは即時実行して、2年目からは FOT.task.while で回しています。
年数分のループが終わるまで true を返して、最後の実行時に終了処理をして戻り値なしで終わります。
実行時点でループ回数が決定しているので FOT.task.while ではなく FOT.task.loop でもいいんですが、
処理中に次のカレンダー表示が始まった場合に中断できるようにしています(関数 loop() の1行目)。
FOT.task に渡す関数は引数を設定できませんが、この例を見て分かる通り、 関数ごと取り込んで外の変数を見ればいいので問題にはならないはずです。 これが問題になるような大規模なプログラムでの利用を想定してません:-)
実際のところ、そこらのライブラリで同じ機能ぐらいあるだろーとは思ってますがw
自分が作ったオモチャなら、
自分でいくらでもいじり倒せるので、今後もいじり続けるつもりです。