混乱したのでまとめておく。JavaScript自体が標準でDeferredに対応したらしいので、今後需要は減るかもしんないけど。async/awaitだっけ?
Deferredに限らず、レファレンスとか簡単な使い方みたいなのはwebでも見つかるけど、基本の構造とか標準的な使い方まで書いたものは意外と見つからない。
やりたいこと
- HTML上にウィンドウを表示、選択肢「はい」「いいえ」を選ばせる
- 選択が「はい」だったら別ページに遷移
- 選択が「いいえ」だったら「本当にいいですか?」と確認する
- 選択が「本当にいい」だったら処理A
- 選択が「本当はよくない」だったらウィンドウに戻る
DeferredオブジェクトとPromiseオブジェクト
Deferredオブジェクトから一部機能を取り去ったのものがPromiseオブジェクト。 Deferredは任意のタイミングでresolve() / reject()できるが、Promiseは勝手にresolve() / reject()できないようになっている。結果だけやりとりするのにPromiseの方が便利。
Deferredオブジェクト
単純な流れを整理すると、こういうことらしい。
var hoge = $.Deferred();//hogeはDeferredオブジェクト。初期状態は'pending(未処理)' hoge.then(function(){});//then()で終了時のアクションを登録する。この段階では実行されない hoge.resolve();//このタイミングでthen()のコールバックが実行される
関数内でDeferredの処理をする場合は以下。
function foo(){ var hoge =$.Deferred(); hoge.resolve(); return hoge.promise();//hogeをPromiseオブジェクトに変換 } promise = foo(); promise .then(function(){/*成功時の処理を登録*/ },function(){/*失敗時の処理を登録*/});
こうすると、foo()が完了した時には既にDeferred/Promiseオブジェクトはresolvedなので、thenの内容はすぐ実行されることになるみたい。then先に書いてもいいのかな。
問題は戻り値をどうするか
というわけで、私が悩んでいるのは、ダイアログ表示関数の戻りをどうするか。 「はい」「いいえ」を返すようにしたいんだけど、promiseオブジェクトも返したい。
調べてみたら、なんと、resolveに引数を指定できるのね……。
function foo(){ var hoge =$.Deferred(); hoge.resolve('成功!'); return hoge.promise();//hogeをPromiseオブジェクトに変換 } promise = foo(); promise .then(function(fuga){ console.log(fuga);/*成功!*/ },function(){/*失敗時の処理を登録*/});
まだ試してないけど、どうもこういうことらしい。
参考文献
よく分かる jQuery Deferred Kindle版 http://amzn.to/2Dc167E