Promise は、コードの非同期動作をよりエレガントにする抽象化です。これは、タスクが完了したかどうかに関係なく、タスクの結果を表す JavaScript のパラダイムになる可能性があります。
一部の最新ブラウザは、Promise/A 標準に準拠したネイティブ Promise オブジェクトをすでに提供しています。 jQuery1.5では$.Deferred(Promiseオブジェクトに変換可能)が提供されています。多くのよく知られたフレームワークも Promise オブジェクトを提供します。 Promise オブジェクトはすでに JavaScript において非常に重要なパターンとなっており、非同期問題を解決する際に示すその優雅さは、まさに JavaScript に必要なものです。 jQuery の $.Deferred オブジェクトを例として、Promise オブジェクトが非同期の問題をどのように処理するかを見てみましょう。 $.DeferredオブジェクトについてはjQueryの公式サイトで確認できるのでここでは詳しく説明しません。
1. 非同期操作のカプセル化
まず、画像の読み込みを例として、次のコードを見てみましょう:
//加载图片函数 var loadImg = function(url){ var img = new Image() , deferred = $.Deferred() ; img.src = url ; img.onload = function(){ //成功则触发deferred.resolve deferred.resolve( this ) ; } ; img.onerror = function(e){ //失败则触发deferred.reject deferred.reject( e ); } ; //返回promise对象 return deferred.promise() ; } ; //请求图片 var request = loadImg('http://r2.ykimg.com/0515000054AFFC2D6737B343930AFAD6') ; //请求成功 request.done(function(img){ //code }) ; //可以注册多个回调,当请求成功时,会按注册的顺序执行,fail和always也有此性质 request.done(function(img){ // code }); //请求失败 request.fail(function(){ // code }) ; //请求完毕 request.always(function(){ //code });
上記のコードでは、画像の読み込み操作をカプセル化し、それらを $.Deferred に委任し、最後に返す Promise を生成します。このメソッドを使用すると、外部に公開されたコールバックを使用するよりもクリーンで明確になります。これを行うもう 1 つのより重要な理由は、プロミスの接続です。
2. 接続の約束
上の画像をロードするコードを例として、Promise を接続する方法を見てみましょう:
var request = loadImg('http://b1.hucdn.com/upload/item/1411/13/89613257775992_800x800.jpg') ; request.done(function(img){ //code }) ; //request连接别的promise之后返回的promise var request3 = request.then(function(img){ //request执行成功时 连接request1 var request1 = loadImg('http://b1.hucdn.com/upload/item/1410/19/29492535741725_800x800.jpg') ; return request1 ; },function(e){ //request执行失败时 连接request2 var request2 = loadImg('http://b1.hucdn.com/upload/item/1410/19/29492535741725_800x800.jpg') ; return request2 ; }); //request执行并且request1或request2成功执行时 request3.done(function(done){ //code }) ;
Promise オブジェクトは、onResolve と onReject という 2 つのコールバックを受け入れる then メソッドを提供します。コールバックで Promise を返すことで、Promise 間の接続を完了できます。このようにして、非同期操作をシリアルに実行できます。
同時に、jQuery は別の接続メソッドも提供します。コードを参照してください:
var request = loadImg('http://b1.hucdn.com/upload/item/1412/23/48188827139381_800x800.jpg') ; var request1 = loadImg('http://b1.hucdn.com/upload/item/1412/06/50258594673502_800x800.jpg') ; //通过$.when连接promise var request2 = $.when(request,request1) ; request2.done(function(img,img){ //code }) ;
jQuery は、n 個の Promise オブジェクトをパラメータとして受け取ることができる $.when 関数を提供します。これは、Promise の実行結果を結合します。このアプローチを使用すると、複数の非同期操作を並行して実行できます。
3. 終わり
ここでのコードでは、例として画像を読み込みます。同じアプローチを他の非同期操作にも適用できます。たとえば、jQuery で $.ajax と $.fn.animate を呼び出すと、promise が返されます。ノード側では、一部の非同期操作 (データベースの読み取り、ファイルの読み取りなど) を Promise にカプセル化することもできます。次に、複数の Promise に対してマージ操作を実装して、それらをシリアルまたはパラレルで実行します。
添付ファイル: 遅延オブジェクト
Promise オブジェクトの変換に使用されることに加えて、deferred 自体も非常に便利なオブジェクトです。 Promise オブジェクトのようなメソッドとプロパティを提供することに加えて、notify 関数と progress 関数も備えています。これら 2 つの関数は、プログレス バーやウォーターフォール フローを実装するときに非常に役立ちます。
プログレスバーを実装する場合、resolve 関数とdone 関数を使用して、プログレスバーが 100% まで読み取られたときのトリガータイミングとトリガーロジックを定義できます。notify 関数と progress 関数を使用して、トリガータイミングとトリガーを定義できます。読み取り中のプログレスバーの時間。トリガーロジック。リジェクト関数とフェイル関数を使用して、進行状況の読み取りが失敗した場合のトリガー タイミングとトリガー ロジックを定義できます。
ウォーターフォール フローを実装する場合、すべてのデータがページに読み込まれたときに、resolve 関数と Done 関数を使用してトリガーのタイミングとトリガー ロジックを定義できます。notify 関数と progress 関数を使用して、トリガーのタイミングとトリガー時間を定義できます。ウォーターフォール フローが次のページを読み取るためのロジック。