序文
約束のオブジェクトは、実行する操作として理解できます(非同期操作に使用されることがよくあります)。 Promiseオブジェクトを使用した後、コードをチェーンコールの方法で整理して、コードをより直感的にすることができます。さらに、Promise.allのような方法の存在は、複数の操作を同時に実行できるようにすることができるためです。
約束の台頭は、非同期メソッド呼び出しでは、コールバック関数が次々と発生することが多いためです。この状況により、コールバックピラミッドの問題が発生しました。コードを書くのが難しくなく、それが美しいだけでなく、コードを読んでいる人が問題が複雑であることを理解することを困難にします。
例として:
db.save(data、function(data){//何か... db.save(data1、function(data){//何かを行う... db.save(data2、function(data)){//データベースの保存操作があり、リクエストでは3つのテーブルでデータを3回保存する必要があるとします。次に、コードは上記のコードに似ています。この時点で2番目のdb.saveに問題がある場合はどうすればよいですか?この考慮事項に基づいて、 try...catchのようなロジックを使用する必要があります。これはすべての悪の源であり、ノードが最初に広く批判されたという点でもあります。
もう1つの欠点は、3つのセーブの間にフロントアンドバックの依存関係がないと仮定すると、次のステップが実行される前に以前の関数が実行されるのを待つ必要があり、3つのセーブを並列化できず、3つのセーブの後に必要な結果を返すことです。 (または、それを実装するにはスキルが必要です)
残念ながら、私が最初にノードに参加し始めたとき、私はこのような多くの地獄を書きました。
後で、私はまだより多くのフロントエンドコードを書いたので、私はES6と接触し、コールバックのアビスを解くための強力なツールを見つけました。
実際、ES6の約束のずっと前に、Q、When.js、Bluebird、およびその他の図書館は、Promise標準に基づいてすでに約束の車輪を構築していました(Promise/A+を参照)。
(私は記事を読んで、それは理にかなっていると思います。それはあなたが組み込みのネイティブオブジェクトを拡張すべきではないと言っています。このアプローチは将来指向にすることはできません。だからここにヒントがあります:ネイティブの約束を拡張するライブラリを使用する場合は注意してください。)
ここでは、ネイティブの約束のみが議論されています。
ES6の約束
オブジェクトステータスを約束します
約束を詳細に説明する前に、まず理論を取りましょう。
Promise/A+仕様は、Promiseオブジェクトが有限状態マシンであることを規定しています。
3つの状態があります。
1。 pending (実行)
2。 fulfilled (成功)
3。 reject
pendingの場合、初期状態は、終了状態fulfilled 、 rejected (最終状態は、約束のライフサイクルが終了したことを示しています)。
州の移行関係は次のとおりです。
保留中 - >充足、保留中 - >拒否。
さまざまなイベント(実行イベントの成功、実行イベントの失敗など)は、州の移行としてトリガーされます。
約束フォーム
約束は次のようになります:
var promise = new promise(function func(resolve、rexy){//何かをし、おそらく非典型的(成功){return resolve(data);} else {return relject(data);}}); console.log(data);}、function(function(data)){ / eg console.log(date);ここでの変数の約束は、Promise Objectのインスタンスです。
Promiseオブジェクトが作成されると、 func関数のロジックが実行されます。
ロジックが処理され、エラーがない場合、 resolveコールバックは値を特別な場所に渡します。この特別な場所はどこですか?それは次のコードにあります。 thenコールバック関数を使用して、 resolve後に結果を処理します。たとえば、上記のコードでは、値をコンソールに出力するだけです。エラーがある場合は、エラーthen処理するために、2番目のコールバック関数にreject 。
上記の有限状態マシンの理論に沿って、Promise Constructorでコールバック関数コードを実行すると、状態はpendingであり、 resolve後に状態がfulfilled 、状態はreject後にrejectことを知っています。
データフローを約束します
上記は、約束の最初のデータフローです。
面白いのは、 then約束の方法がまだ約束のオブジェクトを返すことができるということです。そのため、 thenの方法を使用して同じ処理を行うことができます。
最初の2つのコールバック関数はthen最初のプロミスオブジェクトの種類を決定しthen返します。
最初の最初thenコールバックが約束のオブジェクトを返さないと仮定すると、2番目の呼び出しthenまだ元のPromiseオブジェクトです。ただし、その解決値は最初の最初のコールバック関数の返品値になります。
1つthen最初のコールバック関数が約束オブジェクトを返し、2番目thenこの新しいPromiseオブジェクトになり、2番目then新しいPromiseオブジェクトがコールバックを解決または拒否して実行するのを待ちます。
私は少しspareしみませんでしたが、私はまだそれについて非常に明確だと感じています。ハハ〜
エラーがどこでも発生した場合、エラーは、2番目のコールバック関数でthen 2番目のコールバック関数に引き渡され、処理されます。エラーが処理されるまで後方にrejectことを理解できます。
さらに、Promiseオブジェクトにはメソッドcatchもあり、エラーを処理するコールバック関数を受け入れます。
今すぐ:
promise.catch(function(err){// err。}を扱う)エラーの処理が類似していると仮定すると、この方法はエラーを中心に均一に処理できます。したがって、その後、メソッドは2番目のコールバックを必要としません〜
同時の約束を制御します
Promiseには「静的方法」 Promise.allがあります(Promise.prototypeではないことに注意してください)。この方法は、約束オブジェクトの配列である要素を受け入れます。
この方法は、Promiseオブジェクトも返します。配列内のすべての約束オブジェクトがresolve場合、 resolve値は、 Promise.allメソッドの返品値の(Promiseオブジェクト)のresolve値として配列として使用され、 then方法で処理できます。配列の約束がreject場合、 reject値はPromise.allメソッドの返品値のreject値です。
非常に不透明な点は次のとおりです。
thenメソッドの最初のコールバック関数によって受信されたresolve値(上記のアレイ)の順序は、 Promise.all Arrayの順序と同じです。
また、 Promise.all Promise.raceに似た方法もあります。これは、 resolve最初の値のみを受け入れることを除いて、配列も受信します。
他のオブジェクトをPromiseオブジェクトに変えます
Promise.resovleメソッドは、Promize Objectをパラメーターとして返すことができます。
2つの状況があります。
渡されたパラメーターの方法がない.then仮定すると、返された約束オブジェクトがresolve状態になり、 resolve値がオブジェクト自体になります。
渡されたパラメーターにthenメソッド( thenableオブジェクトと呼ばれる)があると仮定すると、このオブジェクトのタイプは約束に変更され、そのthenはPromise.prototype.thenメソッドになります。
約束は非同期の解決策ですか?
最後に、非常に重要なことを言ってみましょう。Promiseの機能は、コールバックピラミッドの問題を解決することであり、非同期プロセスの制御に実際に大きな役割を果たしていません。非同期プロセスを制御するために約束を真に使用するには、ES6 generator機能も使用する必要があります。 (たとえば、TJマスターのCOライブラリの実装)。
ただし、ES7にはより素晴らしいソリューションがあります。これはCOに似ていasync/awaitが、ネイティブサポートがあります。待って見てみましょう。
要約します
上記は、JavaScriptES6のネイティブの約束に関するものです。この記事の内容がES6を学習するすべての人に役立つことを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとってください。