前の関連記事:jQuery.Deferred学習メモ(2)jQuery1.8以降のdeferred.then()を使う
jQuery.Deferredオブジェクト以外でもPromiseを返すメソッドがあります。それらを使うとjQuery.Deferredオブジェクトを作らなくてもdeferred.then()でPromiseを返せます。まずはアニメーション関係のメソッドです。
.animate()はPromiseを返す。ただしPromiseに付随する引数は返せない。
jQuery.Deferred学習メモ(2)jQuery1.8以降のdeferred.then()を使うの最後にでてきたテストコード⑦を改造してsetTimeoutの変わりに.animate()を使って次の.always()を待たせてみます。
まずは普通にjQuery.Deferredオブジェクトを新たに作ってreturnするやり方です。
テストコード⑧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<script src= "http://code.jquery.com/jquery-1.9.1.js" ></script> <button id= "btn1" >未完</button><button id= "btn2" >完了</button><button id= "btn3" >失敗</button><br /> <div id= "df_ex" ></div> <script> var df1 = $. Deferred (); function fn1(n) { $( "#df_ex" ). append (df1. state ()+n+ "<br/>" ); } function fn2(n) { var df2=$. Deferred (); var n2; fn1(n); $( "#df_ex" ). animate ( { width : "70%" , opacity: 0.4, marginLeft: "0.6in" , fontSize: "3em" }, {duration:1500, easing: "linear" , complete: function (){n2= "で.alwaysも実行" ; df2. resolve (n2);} } ); return df2; } df1 . then (fn2,fn2,fn1) . always (fn1) $( "button#btn1" ). on ( "click" , function () { df1. notify ( "で.progress実行" ); }); $( "button#btn2" ). on ( "click" , function () { df1. resolve ( "で.done実行" ); }); $( "button#btn3" ). on ( "click" , function () { df1. reject ( "で.fail実行" ); }); </script> |
テストコード⑦ではsetTimeoutの中でfn1(n)を実行しfn1の表示を1秒待たせていましたが、テストコード⑧ではまずfn1を表示させてそれを1.5秒かけて拡大表示のアニメーションにしています。
17行目でdf2をreturnして次の.always()の実行を待たせています。
アニメーション終了後の16行目のdf2.resolve(n2)で待たせているのを再開します。
「完了」ボタンをクリックしてみると、まず22行目の.then()のdoneFilterが実行されて9行目のfn2が呼ばれて12行目のfn1(n)が実行されて、「resolvedで.done実行」が表示されます。
続いて13行目の.animate()で1.5秒かけて字が大きくなって、その後に23行目の.alwaysが実行されて「resolvedで.alwaysも実行」が表示されます。
テストコード⑧では19行目でjQuery.Deferredオブジェクトのdf2をreturnしてunfulfilledのPromise返しましたが、今度は.animate()のPromiseを使ってみます。
テストコード⑨
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<script src= "http://code.jquery.com/jquery-1.9.1.js" ></script> <button id= "btn1" >未完</button><button id= "btn2" >完了</button><button id= "btn3" >失敗</button><br /> <div id= "df_ex" ></div> <script> var df1 = $. Deferred (); function fn1(n) { $( "#df_ex" ). append (df1. state ()+n+ "<br/>" ); } function fn2(n) { fn1(n); return $( "#df_ex" ). animate ( { width : "70%" , opacity: 0.4, marginLeft: "0.6in" , fontSize: "3em" }, {duration:1500, easing: "linear" } ); } df1 . then (fn2,fn2,fn1) . always (fn1) $( "button#btn1" ). on ( "click" , function () { df1. notify ( "で.progress実行" ); }); $( "button#btn2" ). on ( "click" , function () { df1. resolve ( "で.done実行" ); }); $( "button#btn3" ). on ( "click" , function () { df1. reject ( "で.fail実行" ); }); </script> |
「完了」ボタンをクリックしてみるとテストコード⑧と同様な動作をします。
これは.animate()の中でjQuery.deferredオブジェクトが作られて、それをresolveするということが行われているからです。
ですのでテストコード⑧の10行目と16行目に相当するコードは書かなくてもよいわけです。
でも、ちょっと表示されているものが違います?
実は、.then()ではPromiseの引数を返さないといけないのを返していないのです。
テストコード⑦では「で.alwaysも実行」となっていたところが「[object Object]」となっているのはそのためです。
この問題は$.when()を使って解決できました。
jQuery.Deferred学習メモ(5)jQuery.when()で複数PromiseのAND条件を判定のテストコード⑰へ。
引数をそのまま次へ受け渡すときは.then()でなく.done()を使えばいいでしょう。
今度はテストコード⑨で.animate()メソッドをつけたjQueryオブジェクトではなく引数をreturnしてみます。
テストコード⑩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<script src= "http://code.jquery.com/jquery-1.9.1.js" ></script> <button id= "btn1" >未完</button><button id= "btn2" >完了</button><button id= "btn3" >失敗</button><br /> <div id= "df_ex" ></div> <script> var df1 = $. Deferred (); function fn1(n) { $( "#df_ex" ). append (df1. state ()+n+ "<br/>" ); } function fn2(n) { fn1(n); $( "#df_ex" ). animate ( { width : "70%" , opacity: 0.4, marginLeft: "0.6in" , fontSize: "3em" }, {duration:1500, easing: "linear" } ); return "で.alwaysも実行" ; } df1 . then (fn2,fn2,fn1) . always (fn1) $( "button#btn1" ). on ( "click" , function () { df1. notify ( "で.progress実行" ); }); $( "button#btn2" ). on ( "click" , function () { df1. resolve ( "で.done実行" ); }); $( "button#btn3" ). on ( "click" , function () { df1. reject ( "で.fail実行" ); }); </script> |
Promiseの引数はちゃんと受け継がれていますが、.then()の次の.alwaysの実行は待ってくれず、「resolvedで.alwaysも実行」が表示されてからアニメーションが始まります。
Promise animationを返すメソッド
.animate()以外にもアニメーションのメソッドはPromiseを返します。
jQuery API DocumentationでPromise animationを検索するとたくさんでてきます。
.fadeIn() .fadeOut() .fadeToggle() .hide().show() .slideDown() .slideToggle() .slideUp() .toggle()がでてきます。
Promise animationのPromiseは.promise()で引き出して.done()できる
テストコード⑨ではPromise animationのunfulfiledのPromiseを.then()にreturnして次のコードの実行を保留にしましたが、Promise animationのPromiseを.promise()メソッドで取り出すことも可能です。
テストコード⑧の16行目を書き換えて.animate()のPromiseを.promise()で取り出して.done()で受けて同じ処理をさせてみます。
テストコード⑪
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<script src= "http://code.jquery.com/jquery-1.9.1.js" ></script> <button id= "btn1" >未完</button><button id= "btn2" >完了</button><button id= "btn3" >失敗</button><br /> <div id= "df_ex" ></div> <script> var df1 = $. Deferred (); function fn1(n) { $( "#df_ex" ). append (df1. state ()+n+ "<br/>" ); } function fn2(n) { var df2=$. Deferred (); var n2; fn1(n); $( "#df_ex" ). animate ( { width : "70%" , opacity: 0.4, marginLeft: "0.6in" , fontSize: "3em" }, {duration:1500, easing: "linear" } ). promise (). done ( function (){n2= "で.alwaysも実行" ; df2. resolve (n2);}); return df2; } df1 . then (fn2,fn2,fn1) . always (fn1) $( "button#btn1" ). on ( "click" , function () { df1. notify ( "で.progress実行" ); }); $( "button#btn2" ). on ( "click" , function () { df1. resolve ( "で.done実行" ); }); $( "button#btn3" ). on ( "click" , function () { df1. reject ( "で.fail実行" ); }); </script> |
これは.animate()の中で作られたPromiseがfulfilledになっときに.done()するということです。
.done()の他に.then(), .fail(), .always(), .progress(), .state()も使えるようです。
Promiseを理解したあとならテストコード⑧の書き方よりこのテストコード⑪の書き方の方がわかりやすいかもしれませんね。
参考にしたサイト
animate(params, options) - jQuery 日本語リファレンス
.animate()の第2引数以降をオプションで指定するやり方の解説。
.animate() | jQuery API Documentation
本家の.animate()の解説。
.animate() | 私的なjQuery
日本語で詳しく.animate()が解説されています。
.promise() | jQuery API Documentation
.promise()の本家の解説。
0 件のコメント:
コメントを投稿