序文
第一の溶液は、AJAXなどの非同期コールバック、コールバックイベント、のsetInterval / setTimeoutをコールバックです。しかし、問題のコールバック関数コールバック地獄。
コールバック地獄の問題を解決するために、コミュニティの約束はES6が言語標準に書き込むことが、解決策を提案しました。コールバック地獄の問題を解決しますが、ある程度そこ約束約束、このようなエラーなどいくつかの問題、上のキャッチを試みることができない、と連鎖の使用は約束を呼び出して、実際には、ちょうどのために、問題が根本的にコールバック地獄を解決しません執筆。
ジェネレータ関数はES6を導入し、発電機は、発電機機能がコルーチンES6に実装され、非同期プログラミング・ソリューションであり、最大の特徴は、右側の関数の実装では、関数は、コンテナジェネレータ非同期タスクは、一時停止することがわかります場所は、yield文が付いています。しかし、発電機は、より複雑なを使用します。
非同期/のawait、非同期は、非同期/のawait、シンタックスシュガージェネレータ機能である非同期コードを同期コードのように見えます、非同期プログラミングの開発目標は、非同期論理コードが同じ同期のように見えるようにすることです:ES7も新しい非同期ソリューションを提案しました。
同期および非同期
ここでは、同期および非同期ルアンYifeng教師の概念上の参考記事。これらのうちのいくつかは、次のような非同期ソリューションの一例である「4つの方法のjsの非同期プログラミング」、 「非同期操作の概要」。
非同期ソリューション
コールバック関数
1 // ノードがファイルを読み取る 2 fs.readFile( 'URL'、 'UTF-8'、関数(ERR、データ){ 3。 // コード 4。 })。
使用シナリオは以下のとおりです。AJAX要求、イベントのコールバック関数、ノードAPI、タイマー。
長所:シンプル。短所:維持が困難と不便な統一処理エラーをコーディングする非同期コールバックのネストされた鉛、できない 、とコールバック地獄の問題があります。try,catch
// 次に、コールバック地獄問題読み取るテキスト、B A Cに応じてテキストを読み、次いで、Bの内容を読み取る..例 fs.readFile(「A」、「UTF-8」、関数(ERR 、データ){ fs.readFile( 'B'、 'UTF-8'、関数(ERR、データ){ fs.readFile( 'C'、 'UTF-8'、関数(ERR、データ){ fs.readFile( 'D'、 'UTF-8'、関数(ERR、データ){ // コード }); }); }); });
約束する
コールバック地獄の問題を解決するため、ある程度の約束、約束が最初に提案され、実施された、ES6をコミュニティプロミスによって提供される標準言語、統一使用、ネイティブオブジェクトに書き込まれます。「ECMAScriptの6入門します」
プロミスコールバック地獄の問題を解決することを目的とする方法を見てみましょう。
関数読み取る(URL){ 戻り 、新たな約束((決意、リジェクト)=> { fs.readFile(URL、 'UTF-8'、関数(ERR、データ){ 場合(ERR)リジェクト(ERR); 解決(データ) ; }); }); } 読み取る( 'A')を(データ=> { リターン読み出す( 'B' ); })。次に、(データ => { リターン読み出す( 'C' ); })。次に、(データ => { 戻りリード( 'D' ); })キャッチ(ERR => {
にconsole.log(ERR);
});
プロミスの利点:ステータス変更一度1.、この結果を得ることができ、いつでも、変更されません。2.プロセスは、深くネストされたコールバックを回避するために、発現同期動作に非同期動作であってもよいです
欠点約束:1.あなたは約束をキャンセルすることはできません。保留状態2.一方は、進行が現在どこの段階を知る方法はありません。3.エラーはすることはできません trycatch
その後、A、Bを読み出し、ファイルのC 3つのコンテンツが正常に読み取られる前の約束を与える、とすることは実施例の最終結果を出力します。これは、サブスクリプションモデルのリリースに依存しています
せpubsup = { ARRY:[]、 放出:関数(){ この .arry.forEach(FN => FN()); }、 で:関数(FN){ この.arry.push(FN)。 } }。 データを聞かせ = []; pubsub.on(() => { 場合(data.length == 3 ){ にconsole.log(データ); } })。 fs.readFile( 'A'、 'UTF-8'、関数(ERR、データ){ data.push(データ); pubsup.emit(); }); fs.readFile( 'B'、 'UTF-8'、関数(ERR、データ){ data.push(データ)。 pubsup.emit(); }); fs.readFile( 'C'、 'UTF-8'、関数(ERR、データ){ data.push(データ); pubsup.emit(); });
ちなみに公園は、簡単な言葉で説明し精神的な練習は、データを非同期的に見て非常に価値がある、異なるシナリオの下で動作し得るnodejs。
約束を提供してくれ 、我々が使用することができ、この需要のための方法 を達成します。Promise.all
Promise.all
/ * * *パッケージ化fs.readFile約束インタフェース * / 関数読み取り(URL){ 戻り 新しい新しいプロミス((解決拒否)=> { fs.readFile(URL、 'UTF-8'、関数(ERR、データ) { IF (ERR)は(ERR)を拒否; 解決(データ); }); }); } / * * 問題* Promise.all複数の非同期並列実行を実現することができ、最終的な結果を得るために同じ時間 * / Promise.all( [ リード(A)、 リード(B)、 リード(C) ])を(データ。 => { にconsole.log(データ); }。)キャッチ(ERR =>にconsole.log(ERR))。
ジェネレータ
ジェネレータ関数はES6が提供する非同期プログラミング・ソリューションで、全体のパッケージは、関数発生器の非同期タスク、コンテナまたは非同期タスクです。非同期操作はyield文でマークされ、場所を一時停止する必要があります。
ジェネレータ機能は、典型的には、プロミスまたは収率で使用されています。ジェネレータ関数は、イテレータを返します。基準発生器の下で先発ES6ルアンYifengと学生がイテレータを理解していないために
関数 * ジェネレータ(){ LETのA =収率111 ; にconsole.log(A) のlet B =収率222 ; にconsole.log(B); LETのC =収率333 ; にconsole.log(C); LETのD =収率444 ; にconsole.log(D); } LET T = ジェネレータ(); // 次に方法は、発現収率の戻り値として扱われるパラメータとることができる t.nextを(1); // 最初の次の呼び出し関数は、無効な引数が渡さ t.next(2); // 出力2 t.nextを(3); // 3 t.next(4); // 4 t.next(5); / / 5
一層テキストはreadFileのは、(テキストを読み取り、テキストコンテンツBを再読み込みするようにB AのC係るに従って読み出すために)、例えば、発電+ COライブラリを使用して実装します。
CONSTのfs =は( 'FS'を必要とします)。 constの共同 =(「コ」が必要です)。 CONSTブルーバード =は(「ブルーバード」が必要)。 CONST readFileの = bluebird.promiseify(fs.readFile)。 関数 * リード(){ 収率readFileの( 'A'、 'UTF-8' )。 収率readFileの( 'B'、 'UTF-8' )。 収率readFileの( 'C'、 'UTF-8' )。 } CO(読み取り())。次いで、(データ => { // コード })。キャッチ(ERR => { // コード })。
await /非同期
ES7は非同期を導入/概念を待っています。非同期は、それが機能にパッケージ化、発電機能と自動アクチュエータ(CO)の実現であり、実際には糖衣構文です。
/コードを待つ非同期の利点は明らかである、それはコールバック地獄に対処することができ、プロミスチェーンのような多くのことを書いていません。そして、エラーがキャッチを試みることができます。
非同期/を使用して一層テキスト(次に読み取るためのテキスト、およびB A Cに従って再読み込みテキストコンテンツBに従ってて読ま)readFileの例としては、達成待ちます。
CONSTのfs =は( 'FS'を必要とします)。 constの共同 =(「コ」が必要です)。 CONSTブルーバード =は(「ブルーバード」が必要)。 CONST readFileの = bluebird.promiseify(fs.readFile)。 非同期関数リード(){ readFileのを待つ( 'A'、 'UTF-8' )。 (readFileのを待つ 'UTF-8'、 'B' )。 (readFileのを待つ 'UTF-8'、 'C' )。 } CO(読み取り())。次いで、(データ => { // コード })。キャッチ(ERR => { // コード })。
私たちは、/非同期を使用するのと同じ効果を達成するために待っています。
関数読み取る(URL){ 戻り 、新たな約束((決意、リジェクト)=> { fs.readFile(URL、 'UTF-8'、関数(ERR、データ){ 場合(ERR)リジェクト(ERR); 解決(データ) ; }) })。 } 非同期関数readAsync(){ CONSTデータ =は([Promise.allを待つ (A)を読み取り、 (B)を読んで、 (C)を読み取ります ])。 返すデータを、 } 。READSYNC()を(データ => { にconsole.log(データ); })
だから、JSの非同期開発の歴史は、コールバックから考えることができる - >約束 - >発電 - >非同期/待っています。非同期/非同期コードは、ターゲット同期コードのように見えます、非同期プログラミングの開発は、非同期論理コードが同じ同期のように見えるようにすることです待ちます