1. ki-sato

    Posted

    ki-sato
Changes in title
+JQuery.Deferredでwait風メソッド
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,66 @@
+javascriptで実行待ちの場合、setTimeout使えばいいんですがいちいちコールバック関数として引き渡してやる必要があるのでたとえば2秒待った後に1秒待つ、といったように実装する際、コールバックがネストし、見ていてやるせないコードになります。
+(そんな設計するのがそもそも悪いってのもあるかもしれませんが)
+例えばこんな感じ。
+
+```js
+setTimeout(function(){
+ // 2000ms 待った後に実行されるコールバック
+ setTimeout(function(){
+ // 1000ms 待った後に実行されるコールバック
+ // その何秒後かにまた実行するコードを書くとさらにネストが下がっていく...
+ },1000);
+},2000);
+```
+
+ネストが2個とかそこらならまだ許容範囲かもしれませんが、
+どうせならJQuery.Deferredを使ってネストをあまり下げないように書いてしまいましょう。
+
+まずは以下のようなメソッドを定義しておきます。
+
+```js
+$.wait = function(msec) {
+ // Deferredのインスタンスを作成
+ var d = new $.Deferred;
+
+ setTimeout(function(){
+ // 指定時間経過後にresolveしてdeferredを解決する
+ d.resolve(msec);
+ }, msec);
+
+ return d.promise();
+};
+```
+
+見ての通り、別にむずかしいことはやってません。
+引数のチェック等は必要であれば適宜入れておくといいと思います。
+
+使い方は下記のような感じです。
+
+```js
+$.wait(2000)
+ .done(function(){
+ console.log("2000ミリ秒待ちました");
+ });
+```
+
+doneでコールバックを登録することで指定した時間経過後に実行するメソッドを定義できます。
+また最初にあげたような多段の場合ですが、こちらはthenで指定して中で再度waitをコールし、返ってきたdeferredをreturnしてやれば次のチェーンに引き渡せます。
+
+具体的には以下のような感じです。
+
+```js
+$.wait(2000)
+ .then(function(ms){
+ console.log(ms + "ミリ秒待ちました");
+ // 次のコールバックに渡すために新たなdeferredを返却
+ return $.wait(1000);
+ // 次のコールバックも同様のやり方でつなげばいくらつないでもネストはこれ以上下がらない
+ })
+ .done(function(ms){
+ console.log(ms + "ミリ秒待ちました");
+ });
+```
+
+これでまず2000ms待ってから、コンソールに表示し、さらに1000秒待ってからコンソールに表示、といったような動きをします。
+thenの中でwaitのdeferredをreturnというのを繰り返すことでネストを深くせずにチェーンを連続して書けます。
+ちなみにwaitの中でresolveする時にwaitの引数をそのまま渡しているのでコールバックの中でそれを引数として受け取れます。