javascript で wait処理
Javascriptではwait処理はない。
でも、ある処理Aが完了した後に、処理Bをして欲しい場合が往々にしてある。
例えば、以下のような処理。
var a = func1();
func2(a);
通常の場合だと、この処理はfunc1 → func2と処理される。
だけどfunc1の中で、setTimeoutやsetIntervalが利用されてると、
うまくいかないケースがある。
例えば、以下のケースを実行すると
var a = 0; function func1(){ if( a < 10){ a++; alert("hoge" + a); setTimeout("func1()", 500); } else{ alert("END"); return a } } function func2(val){ alert ("call func2: " + val); } var value = func1(); func2(value);
実行結果は
hoge1 call func2: undefined ← ココですでに呼ばれてしまっている!! hoge2 hoge3 hoge4 hoge5 hoge6 hoge7 hoge8 hoge9 hoge10 END
となる。
つまり、func1 → func2 → func1 → func1.... となる 。
この辺についてはid:amachangのこの記事が参考になります。(JavaScript を学ぶ際に一番重要なのに、誤解されがちな setTimeout 系の概念)
なんとかwaitみたいな処理が出来ないか考えて見ました。
webをクロールすると2種類の方法が在るようです。
- for か while でグルグル回す。
- setTimeout か setIntervalを利用する。
1はあり得ないですよね。
というわけで、2の方法で模索してみました。
軽くweb上をググってみるとこのような記事が目につきますが
ぶっちゃけ、ややこしすぎてわからんw。
いや、わかるんやけど、汎用的にしようとして余計なコードが多すぎる(と私は思いますと言ってみるテスト)。
なので、やっぱり自分で作ってみました。
こんな感じのコードで至ってシンプル。
timerID = setInterval(function(){ if(waitの終了条件){ wait終了時の後処理 clearInterval(timerID); timerID = null; } }, 20); // polling time = 20ms
で出来ました。
先ほどの例を作った形に当てはめると。
var a = 0; function func1(){ if( a < 10){ a++; alert("hoge" +a); } else{ alert("END"); return a } } function func2(val){ alert ("call func2: " + val); } timerID = setInterval( function(){ value = func1(); if(value == 10){ func2(value); clearInterval(timerID); timerID = null; } },1000);
んで、実行結果は
hoge1 hoge2 hoge3 hoge4 hoge5 hoge6 hoge7 hoge8 hoge9 hoge10 END call func2: 10
わーーーー、わーーーーー、パチパチパチ!!!
気をつけなきゃいけない箇所はwait終了条件、
このサンプルプログラムを作るときに間違えてif(value < 10 )と間違えてはまったのは内緒の話だ。
このwait処理の実行条件としては、setInterval内で利用する変数(例えばループ終了条件)については、
setIntervalの外で宣言しないとだめな点かもしれない。
追伸
試してないけど、このコードってこうしたら汎用的につかえね??
/* 引数1: wait終了条件 引数2: wait終了後のコールバック関数 引数3: ポーリング時間 戻り値 正常に終了したかどうか */ function wait(flag, fanc, timer){ var _flag = flag; var _func = func; var _timer = timer; timerID = setInterval(function(){ if(eval(_flag)){ clearInterval(timerID); timerID = null; _func(); } }, _timer); }