LoginSignup
32
33

More than 1 year has passed since last update.

[2013年版] JQuery.Deferredでwait風メソッド

Last updated at Posted at 2013-12-27

javascriptで実行待ちの場合、setTimeout使えばいいんですがいちいちコールバック関数として引き渡してやる必要があるのでたとえば2秒待った後に1秒待つ、といったように実装する際、コールバックがネストし、見ていてやるせないコードになります。
(そんな設計するのがそもそも悪いってのもあるかもしれませんが)
例えばこんな感じ。

setTimeout(function(){
    // 2000ms 待った後に実行されるコールバック
    setTimeout(function(){
      // 1000ms 待った後に実行されるコールバック
      // その何秒後かにまた実行するコードを書くとさらにネストが下がっていく...
    },1000);
},2000);

ネストが2個とかそこらならまだ許容範囲かもしれませんが、
どうせならJQuery.Deferredを使ってネストをあまり下げないように書いてしまいましょう。

まずは以下のようなメソッドを定義しておきます。

$.wait = function(msec) {
    // Deferredのインスタンスを作成
    var d = new $.Deferred;

    setTimeout(function(){
        // 指定時間経過後にresolveしてdeferredを解決する
        d.resolve(msec);
    }, msec);

    return d.promise();
};

見ての通り、別にむずかしいことはやってません。
引数のチェック等は必要であれば適宜入れておくといいと思います。

使い方は下記のような感じです。

$.wait(2000)
  .done(function(){
      console.log("2000ミリ秒待ちました");
  });

doneでコールバックを登録することで指定した時間経過後に実行するメソッドを定義できます。
また最初にあげたような多段の場合ですが、こちらはthenで指定して中で再度waitをコールし、返ってきたdeferredをreturnしてやれば次のチェーンに引き渡せます。

具体的には以下のような感じです。

$.wait(2000)
  .then(function(ms){
      console.log(ms + "ミリ秒待ちました");
      // 次のコールバックに渡すために新たなdeferredを返却
      return $.wait(1000); 
      // 次のコールバックも同様のやり方でつなげばいくらつないでもネストはこれ以上下がらない
  })
  .done(function(ms){
      console.log(ms + "ミリ秒待ちました");
  });

これでまず2000ms待ってから、コンソールに表示し、さらに1000ms待ってからコンソールに表示、といったような動きをします。
thenの中でwaitのdeferredをreturnというのを繰り返すことでネストを深くせずにチェーンを連続して書けます。
ちなみにwaitの中でresolveする時にwaitの引数をそのまま渡しているのでコールバックの中でそれを引数として受け取れます。

jQuery.deferredについて更に知りたい方は下記を参照ください。
https://www.null-engineer.ml/

非jQueryで実装する方法

32
33
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
33