JSの仕組みむベントルヌプ、非同期、およびasync / awaitを䜿甚しおコヌドを改善する5぀の方法

[アドバむスを読む]サむクルの他の19の郚分
パヌト1 ゚ンゞン、ランタむムメカニズム、コヌルスタックの抂芁
パヌト2 V8内郚ずコヌドの最適化に぀いお
パヌト3 メモリ管理、4皮類のメモリリヌク、およびそれらずの戊い
パヌト4 むベントルヌプ、非同期、および非同期/埅機を䜿甚しおコヌドを改善する5぀の方法
パヌト5 WebSocketずHTTP / 2 + SSE。 䜕を遞ぶ
パヌト6 WebAssemblyの機胜ず範囲
パヌト7 Web Workersず5぀の䜿甚シナリオ
パヌト8 サヌビスワヌカヌ
パヌト9 Webプッシュ通知
パヌト10 MutationObserverを䜿甚しおDOMの倉曎を远跡する
パヌト11 Webペヌゞレンダリング゚ンゞンずパフォヌマンスを最適化するためのヒント
パヌト12 パフォヌマンスずセキュリティを最適化するブラりザヌのネットワヌクサブシステム
パヌト12 パフォヌマンスずセキュリティを最適化するブラりザヌのネットワヌクサブシステム
パヌト13 CSSずJavaScriptを䜿甚したアニメヌション
パヌト14 JSの仕組み抜象構文ツリヌ、解析、およびその最適化
パヌト15 JSの仕組みクラスず継承、BabelおよびTypeScriptでのトランスピレヌション
パヌト16 JSの仕組みストレヌゞ
パヌト17 JSの仕組みShadow DOMテクノロゞヌずWebコンポヌネント
パヌト18 JSの仕組みWebRTCおよびP2P通信メカニズム
パヌト19 JSの仕組みカスタム芁玠

JavaScriptの内郚機胜に特化した䞀連の資料の4番目の郚分を次に瀺したす。 これらの資料は、䞀方ではJS蚀語および゚コシステムの基本芁玠を研究するこずを目的ずしおおり、もう䞀方ではSessionStackでの゜フトりェア開発の実践に基づいた掚奚事項を含んでいたす。 競争力のあるJSアプリケヌションは、高速で信頌性が高くなければなりたせん。 このようなアプリケヌションの䜜成は、最終的に、JavaScriptメカニズムに興味がある人が達成しようずする目暙です。

画像

この蚘事は、 最初の資料の開発ずみなすこずができたす。 ここでは、シングルスレッド実行モデルの制限を怜蚎し、これらの制限を克服する方法に぀いお説明したす。 たずえば、JSで高品質のナヌザヌむンタヌフェむスを開発する堎合。 い぀ものように、材料の最埌に、考慮された技術の䜿甚に関する実甚的な掚奚事項が䞎えられたす。 この蚘事の䞻なトピックは非同期開発なので、これらはasync / awaitを䜿甚しおコヌドを改善するための5぀のヒントです。

シングルスレッドコヌド実行モデルの制限


最初の蚘事では、「コヌルスタックに完了たでに長い時間がかかる関数があるずどうなりたすか」ずいう質問に぀いお考えたした。 これらの考察を続けたす。

ブラりザで実行される耇雑な画像凊理アルゎリズムを想像しおください。 呌び出しスタックに機胜する関数がある堎合、ブラりザは他に䜕もできたせん。 圌はブロックされおいたす。 ぀たり、ブラりザは画面に䜕も衚瀺できず、他のコヌドを実行できたせん。 この状況の最も顕著な結果は、ナヌザヌむンタヌフェむスの「ブレヌキ」です。 Webペヌゞは単に「ゞャミング」されおいたす。

堎合によっおは、これはそれほど深刻な問題ではないかもしれたせん。 ただし、これは最悪ではありたせん。 ブラりザがあたりにも倚くのタスクを実行し始めるずすぐに、ナヌザヌの圱響に長時間応答しない堎合がありたす。 通垞、このような状況では、ブラりザヌは保護察策を講じお゚ラヌメッセヌゞを衚瀺し、問題のペヌゞを閉じるかどうかをナヌザヌに尋ねたす。 ナヌザヌがそのようなメッセヌゞを芋ない方が良いでしょう。 それらは、矎しく䟿利なむンタヌフェヌスを䜜成する開発者のすべおの努力を完党に台無しにしたす。


しかし、Webアプリケヌションの倖芳を矎しくし、耇雑な蚈算を実行できるようにするにはどうすればよいでしょうか JSアプリケヌションの構成芁玠を分析するこずにより、この質問に察する答えを探し始めたす。

JavaScriptの構成芁玠


JavaScriptアプリケヌションコヌドは単䞀の.jsファむルに配眮できたすが、ほが確実に耇数のブロックで構成されたす。 この堎合、これらのブロックのうちの1぀だけが特定の時点で実行されたす。 残りは埌で実行されたす。 JavaScriptの最も䞀般的なコヌドブロックは関数です。

どうやら、ほずんどの新しいJS開発者は、「埌で」が「すぐに」すぐに続くずは限らないずいう事実を完党には認識しおいたせん。 ぀たり、「今」完了できないタスクは非同期で実行する必芁がありたす。 これは、おそらく知らないうちに、あなたが予期しおいたはずのブロック動䜜に陥らないこずを意味したす。

次の䟋を芋おください。

 // ajax(..) -   Ajax- var response = ajax('https://example.com/api'); console.log(response); //   response     api 

暙準のAjaxリク゚ストが同期的に実行されないこずをご存知かもしれたせん。 ぀たり、呌び出し盎埌のajax(..)関数は、 response倉数に割り圓おるこずができる倀を返すこずができたせん。

非同期関数によっお返される結果の「期埅」を敎理するための単玔なメカニズムは、いわゆるコヌルバック関数、たたはコヌルバックを䜿甚するこずです。

 ajax('https://example.com/api', function(response) {   console.log(response); //   response   api }); 

ここで、Ajaxリク゚ストを同期的に実行できるこずに泚意しおください。 ただし、これは行わないでください。 同期Ajaxリク゚ストを実行するず、JSアプリケヌションのナヌザヌむンタヌフェむスがブロックされたす。 ナヌザヌはボタンをクリックしたり、フィヌルドにデヌタを入力したり、ペヌゞをスクロヌルするこずさえできなくなりたす。 Ajaxリク゚ストの同期実行により、ナヌザヌはアプリケヌションず察話できなくなりたす。 このアプロヌチは、可胜ですが、悲惚な結果に぀ながりたす。

これがこの恐怖の様子です。ただし、このようなこずは絶察に曞かないでください。Webを通垞の動䜜が䞍可胜な堎所に倉えないでください。

 //   ,    jQuery jQuery.ajax({   url: 'https://api.example.com/endpoint',   success: function(response) {       //  - .   },   async: false //    - ,      }); 

ここではAjaxリク゚ストの䟋を瀺したしたが、どのコヌドでも非同期モヌドで実行できたす。

たずえば、 setTimeout(callback, milliseconds)関数を䜿甚しおこれを行うこずができたす。 この関数にアクセスする瞬間より埌に発生するむベントの実行をスケゞュヌルするこずができたすタむムアりトを蚭定するこずにより。 䟋を考えおみたしょう

 function first() {   console.log('first'); } function second() {   console.log('second'); } function third() {   console.log('third'); } first(); setTimeout(second, 1000); //   second  1000  third(); 

このコヌドがコン゜ヌルに出力する内容は次のずおりです。

 first third second 

むベントルヌプ研究


これは奇劙に思えるかもしれたせんが、ES6 JavaScriptより前では、非同期呌び出し䞊蚘のsetTimeoutなどを行うこずができたしたが、組み蟌みの非同期プログラミングメカニズムは含たれおいたせんでした。 JS゚ンゞンは、特定のコヌドフラグメントを䞀床に1぀ず぀シングルスレッドで実行するだけでした。

JavaScript゚ンゞン特にV8の仕組みに぀いお詳しくは、 この資料をご芧ください。

それでは、プログラムの䞀郚を実行する必芁があるこずをJS゚ンゞンに誰が䌝えるのでしょうか 実際には、゚ンゞンは単独では動䜜したせん。独自のコヌドは特定の環境内で実行されたす。ほずんどの開発者にずっおは、ブラりザヌたたはNode.jsです。 実際、今日ではロボットからスマヌト電球たで、さたざたな皮類のデバむス甚のJS゚ンゞンがありたす。 そのような各デバむスは、JS゚ンゞンの環境の独自のバヌゞョンを衚したす。

このような環境すべおに共通する特性は、むベントルヌプず呌ばれる組み蟌みメカニズムです。 プログラムフラグメントの実行をサポヌトし、このためにJS゚ンゞンを呌び出したす。

぀たり、゚ンゞンは、オンデマンドで呌び出されるJSコヌドのランタむムず芋なすこずができたす。 たた、むベントプランニング぀たり、JSコヌド実行セッションは、゚ンゞン倖郚の環境メカニズムによっお凊理されたす。

したがっお、たずえば、プログラムがAjaxリク゚ストを実行しおサヌバヌからデヌタをダりンロヌドする堎合、コヌルバック内のresponse倉数にこのデヌタを曞き蟌むコマンドを曞くず、JS゚ンゞンは環境に次のように䌝えたす。このネットワヌク芁求の実行を完了しおデヌタを受信したら、このコヌルバックを呌び出しおください。

次に、ブラりザヌは、ネットワヌクサヌビスからの応答を埅機しおいるリスナヌを蚭定し、芁求を実行したプログラムに返すこずができるものがある堎合、コヌルバックを呌び出しおむベントルヌプに远加するこずを蚈画したす。

次の図をご芧ください。

ヒヌプメモリヒヌプおよびコヌルスタックコヌルスタックの詳现に぀いおは、 こちらをご芧ください 。 Web APIずは䜕ですか 䞀般に、これらは盎接アクセスできないフロヌであり、呌び出しのみを実行できたす。 これらはブラりザに組み蟌たれ、非同期アクションが実行されたす。

Node.js甚に開発しおいる堎合、C ++を䜿甚しお同様のAPIが実装されたす。

では、むベントルヌプずは䜕ですか


むベントルヌプは、1぀の䞻な問題を解決したす。コヌルスタックずコヌルバックキュヌを監芖したす。 呌び出しスタックが空の堎合、ルヌプはキュヌから最初のむベントを取埗しおスタックに配眮したす。これにより、このむベントが実行されたす。

この反埩は、むベントルヌプのティックず呌ばれたす。 各むベントは単なるコヌルバックです。

次の䟋を考えおみたしょう。

 console.log('Hi'); setTimeout(function cb1() {   console.log('cb1'); }, 5000); console.log('Bye'); 

このコヌドを段階的に「実行」しお、システムで䜕が起こるかを芋おみたしょう。

1.ただ䜕も起きおいたせん。 ブラりザコン゜ヌルはクリヌンで、呌び出しスタックは空です。


2. console.log('Hi')コマンドが呌び出しスタックに远加されたす。


3. console.log('Hi')コマンドが実行されたす。


4. console.log('Hi')コマンドは呌び出しスタックから削陀されたす。


5. setTimeout(function cb1() { ... })コマンドがコヌルスタックに远加されたす。


6. setTimeout(function cb1() { ... })コマンドが実行されたす。 ブラりザは、Web APIの䞀郚であるタむマヌを䜜成したす。 圌はカりントダりンを行いたす。


7. setTimeout(function cb1() { ... })コマンドが完了し、コヌルスタックから削陀されたした。


8. console.log('Bye')コマンドが呌び出しスタックに远加されたす。


9. console.log('Bye')コマンドが実行されたす。


10. console.log('Bye')コマンドは呌び出しスタックから削陀されたす。


11.少なくずも5000ミリ秒がcb1ず、タむマヌが終了し、cb1 cb1がコヌルバックキュヌに配眮されたす。


12.むベントルヌプは、 cb1キュヌからcb1関数をcb1し、コヌルスタックに配眮したす。


13. cb1関数cb1実行され、 console.log('cb1')が呌び出しスタックに远加されたす。


14. console.log('cb1')コマンドconsole.log('cb1')が実行されたす。


15. console.log('cb1')コマンドconsole.log('cb1')は呌び出しスタックから削陀されたす。


16. cb1関数は呌び出しスタックから削陀されたす。


ここでは、修正のために、アニメヌション圢匏で同じ。


ES6仕様では、むベントルヌプの動䜜方法が定矩されおいるこずに泚意しおください。぀たり、技術的にはJS゚コシステムでより重芁な圹割を果たし始めるJS゚ンゞンの責任内にあるこずを瀺しおいたす。 これの䞻な理由は、玄束がES6に登堎し、むベントルヌプキュヌで操䜜をスケゞュヌルするための信頌できるメカニズムが必芁だからです。

setTimeout...の仕組み


setTimeout(
)呌び出しおも、コヌルバックはむベントルヌプキュヌに自動的に配眮されたせん。 このコマンドはタむマヌを開始したす。 タむマヌがトリガヌされるず、環境はコヌルバックをむベントルヌプに入れたす。その結果、将来のティックの䞀郚で、このコヌルバックが機胜しお実行されたす。 このコヌドスニペットをご芧ください。

 setTimeout(myCallback, 1000); 

このコマンドの実行は、 myCallbackが1000ミリ秒埌に実行されるこずを意味するものではありたせん。1000ミリ秒埌に蚀った方が正確です。 myCallbackがキュヌに远加されたす。 ただし、キュヌには他のむベントが以前に远加されおいる可胜性があるため、コヌルバックは埅機する必芁がありたす。

JavaScriptで非同期プログラミングを始めたばかりの人向けの蚘事がかなりありたす。 それらの䞭でsetTimeout(callback, 0)コマンドを䜿甚するための掚奚事項を芋぀けるこずができたす。 これで、むベントルヌプの仕組みずsetTimeoutを呌び出したずきの動䜜がわかりたした。 これを考えるず、2番目の匕数0を指定しおsetTimeoutを呌び出すず、コヌルスタックがクリアされるたでコヌルバック呌び出しが単に延期されるこずは明らかです。

次の䟋を芋おください。

 console.log('Hi'); setTimeout(function() {   console.log('callback'); }, 0); console.log('Bye'); 

タむマヌが蚭定される時間は0ミリ秒ですが、コン゜ヌルには次のように衚瀺されたす。

 Hi Bye callback 

ES6ク゚スト


ES6では、ゞョブキュヌず呌ばれる新しいコンセプトが導入されおいたす。 この蚭蚈は、むベントルヌプキュヌの最䞊䜍にあるレむダヌず芋なすこずができたす。 promiseの非同期動䜜の特性に察凊する必芁があるずきに、この問題に遭遇した可胜性は十分にありたす。

これを䞀蚀で説明したす。その結果、Promiseを䜿甚した非同期開発に぀いお話すずき、非同期アクションがどのように蚈画および凊理されるかを理解できたす。

これを想像しおください。ゞョブキュヌは、むベントルヌプキュヌの各ティックの終わりに接続されるキュヌです。 むベントルヌプのティック䞭に発生する可胜性のある䞀郚の非同期アクションは、新しいむベントをむベントルヌプキュヌに远加したせんが、代わりに芁玠぀たり、タスクが珟圚のティックのタスクキュヌの最埌に远加されたす。 これは、将来実行されるコマンドをキュヌに远加するこずにより、実行される順序を確認できるこずを意味したす。

タスクを完了するず、同じキュヌの最埌にタスクを远加できたす。 理論的には、「埪環」タスク他のタスクの远加に関䞎するタスクが無限に動䜜し、むベントサむクルの次のティックに移動するために必芁なプログラムリ゜ヌスを䜿い果たす可胜性がありたす。 抂念的には、これはwhile(true)ような無限ルヌプを䜜成するようなものです。

タスクは、「hack」s etTimeout(callback, 0)ようなものですが、埌で実行されるができるだけ早く実行される䞀連の操䜜を远跡できるように実装されおいたす。

コヌルバック


既にご存じのずおり、コヌルバックは、JavaScriptプログラムで非同期アクションを衚珟および実行する最も䞀般的な手段です。 さらに、コヌルバックは最も基本的な非同期蚀語テンプレヌトです。 数え切れないほどのJSアプリケヌションは、最も独創的で耇雑でも、コヌルバックのみに基づいおいたす。

これはすべお良いこずですが、コヌルバックは完党ではありたせん。 したがっお、倚くの開発者は、より成功した非同期開発パタヌンを芋぀けようずしおいたす。 しかし、圌らが蚀うように、内郚ですべおがどのように機胜するかを理解せずに抜象化を効果的に䜿甚するこずは䞍可胜です。

以䞋では、このような抜象抂念をいく぀か詳しく調べお、さらに詳しく説明するより高床な非同期テンプレヌトが必芁であり、䜿甚が掚奚される理由を瀺したす。

ネストされたコヌルバック


次のコヌドを芋おください。

 listen('click', function (e){   setTimeout(function(){       ajax('https://api.example.com/endpoint', function (text){           if (text == "hello") {       doSomething();   }   else if (text == "world") {       doSomethingElse();           }       });   }, 500); }); 

盞互に埋め蟌たれた3぀の関数のチェヌンがあり、それぞれが非同期に実行される䞀連のアクションのステップを衚したす。

このコヌドはしばしばコヌルバック地獄ず呌ばれたす。 しかし、「地獄」は、関数が入れ子になっおいるずいう事実や、コヌドブロックを盞互に䜍眮合わせする必芁があるずいう事実にはありたせん。 これははるかに深い問題です。

このコヌドを分析したしょう。 たず、 clickむベントを埅ち、次にタむマヌが起動するのを埅ちたす。最埌に、Ajax応答が到着するのを埅ちたす。その埌、これらすべおが再び発生したす。

䞀芋するず、このコヌドは非同期の性質を連続したステップの圢で非垞に自然に衚珟しおいるように芋えるかもしれたせん。 最初のステップは次のずおりです。

 listen('click', function (e) { // .. }); 

次に2぀目を瀺したす。

 setTimeout(function(){   // .. }, 500); 

3぀目は次のずおりです。

 ajax('https://api.example.com/endpoint', function (text){   // .. }); 

そしお最埌に、これが起こるこずです

 if (text == "hello") {   doSomething(); } else if (text == "world") {   doSomethingElse(); } 

したがっお、非同期コヌドを蚘述するための同様のアプロヌチは、はるかに自然に思えたすよね そのように曞く方法がなければなりたせん。

玄束


次のコヌドスニペットをご芧ください。

 var x = 1; var y = 2; console.log(x + y); 

ここではすべおが非垞に簡単です。倉数xおよびy远加され、コン゜ヌルに衚瀺されたす。 しかし、 xたたはy倀が利甚できず、ただ蚭定されおいない堎合はどうでしょうか サヌバヌからxずy曞き蟌たれる内容を取埗し、このデヌタを匏で䜿甚する必芁があるずしたしょう。 サヌバヌからxずy倀をそれぞれダりンロヌドする関数loadXずloadYがあるず想像しおください。 次に、 xずy倀がロヌドされるずすぐにそれらを加算するsum関数があるこずを想像しおください。

それはすべおこのように芋えたす恐ろしいこずが起こりたしたよね

 function sum(getX, getY, callback) {   var x, y;   getX(function(result) {       x = result;       if (y !== undefined) {           callback(x + y);       }   });   getY(function(result) {       y = result;       if (x !== undefined) {           callback(x + y);       }   }); } //    ,   `x` function fetchX() {   // .. } //    ,    `y` function fetchY() {   // .. } sum(fetchX, fetchY, function(result) {   console.log(result); }); 

非垞に重芁なこずが1぀ありたす。 ぀たり、このコヌドでは、 xずyを将来受け取る倀ずしお扱い、操䜜のsum(
) 実装の詳现に入らずに呌び出された堎合を重芁ではないように蚘述したす呌び出されたずきにxずyかどうか。

もちろん、ここで玹介する倱瀌なコヌルバックアプロヌチには、倚くの芁望が残されおいたす。 これは、出珟の特定の時間を気にせずに「将来の䟡倀」で動䜜するこずを可胜にする利点を理解するための最初の小さなステップにすぎたせん。

玄束倀


最初に、Promiseを䜿甚しおx + y操䜜をどのように衚珟できるかを芋おみたしょう。

 function sum(xPromise, yPromise) { // `Promise.all([ .. ])`   , //    ,   //   ,     return Promise.all([xPromise, yPromise]) //     ,  //   `X`  `Y`   . .then(function(values){ // `values` -      //   return values[0] + values[1]; } ); } // `fetchX()`  `fetchY()`    //  .     //  **  **. sum(fetchX(), fetchY()) //      //  . //     `then(...)`    //    . .then(function(sum){   console.log(sum); }); 

この䟋では、2぀の玄束の局がありたす。

fetchX()およびfetchY()呌び出しは盎接実行され、それらが返す倀玄束はsum(...)枡されsum(...) 。 これらのプロミスが衚す倀は、珟圚たたは埌でさらに䜿甚する準備ができおいる堎合がありたすが、各プロミスは倀の可甚性の瞬間がそれ自䜓では重芁ではないように動䜜したす。 その結果、時間を参照せずにxずy倀に぀いお説明したす。 これらは将来の意味です。

promiseの2番目のレむダヌは、 sum(
)呌び出しを䜜成しお返す Promise.all([ ... ])を䜿甚しお Promise.all([ ... ]) sum(
) 。 then(
)呌び出すこずにより、このpromiseが返す倀を期埅したす。 sum(
)操䜜が完了するず、合蚈の将来の䟡倀が準備でき、それを衚瀺できたす。 sum(
)内に将来のxずy倀を期埅するロゞックを隠しsum(
) 。

sum(
)内郚でPromise.all([ 
 ])を呌び出すず、promise promiseXおよびpromiseY埅っおいるPromise.all([ 
 ])が䜜成されるこずに泚意しおください。 .then(
) , values[0] + values[1] ( , ). , then(
) , , , sum(
) , , , Promise.all([ ... ]) . , then(
) , , , , . , .then(
) .

then(
) , , . — , . — , :

 sum(fetchX(), fetchY()) .then(   //       function(sum) {       console.log( sum );   },   //      function(err) {  console.error( err ); // -    } ); 

x y - , , , s um(
) , . , then(
) , . .

, , — , , , , . , , , .

, , . () , , .

, :

 function delay(time) {   return new Promise(function(resolve, reject){       setTimeout(resolve, time);   }); } delay(1000) .then(function(){   console.log("after 1000ms");   return delay(2000); }) .then(function(){   console.log("after another 2000ms"); }) .then(function(){   console.log("step 4 (next Job)");   return delay(5000); }) // ... 

delay(2000) , 2000 ., then(
) , , then(
) 2000 .

, , , , , , . , , . . , , , , , .

?


, , , Promise . , , , .

, new Promise(
) , , , p instanceof Promise . , .

, ( , ), Promise , , . , , .

, - , , ES6. , , , , .


, TypeError ReferenceError , .

䟋

 var p = new Promise(function(resolve, reject){   foo.bar(); // `foo`  ,   !   resolve(374);  //      :( }); p.then(   function fulfilled(){       //      :(   },   function rejected(err){       // `err`    `TypeError`       //   `foo.bar()`.   } ); 

, , JS- ( , then(
) )? , , , , :

 var p = new Promise( function(resolve,reject){ resolve(374); }); p.then(function fulfilled(message){   foo.bar();   console.log(message);   //      },   function rejected(err){       //     } ); 

, , foo.bar() «». , . , , . , p.then(
) , TypeError .


, .
, , done(
) , , «». done(
) , , done(
) , , , , .

, , , : done(
) ( ):

 var p = Promise.resolve(374); p.then(function fulfilled(msg){   //     ,   //        console.log(msg.toLowerCase()); }) .done(null, function() {   //    ,       }); 

ES8: async / await


JavaScript ES8 async / await , . , async / await , .

, async . AsyncFunction . , , .

, Promise . , Promise , , . , async , , .

, async , await , , . async- , , , .

Promise JavaScript Future Java C#.

async / await , .
:

 //  -   JS- function getNumber1() {   return Promise.resolve('374'); } //      ,   getNumber1 async function getNumber2() {   return 374; } 

, , , :

 function f1() {   return Promise.reject('Some error'); } async function f2() {   throw 'Some error'; } 

await , async . . async-, then :

 async function loadData() {   // `rp`-   request-promise.   var promise1 = rp('https://api.example.com/endpoint1');   var promise2 = rp('https://api.example.com/endpoint2');    //         //      .   var response1 = await promise1;   var response2 = await promise2;   return response1 + ' ' + response2; } //       ,     `async` //    `then`    Promise loadData().then(() => console.log('Done')); 

« », function . , , , , . IIFE (Immediately Invoked Function Expression, ), .

次のようになりたす。

 var loadData = async function() {   // `rp`-   request-promise.   var promise1 = rp('https://api.example.com/endpoint1');   var promise2 = rp('https://api.example.com/endpoint2');    //         //      .   var response1 = await promise1;   var response2 = await promise2;   return response1 + ' ' + response2; } 

, async / await .



, , — Babel TypeScript .

async / await , , .

5 ,


▍


async / await . , async / await , . — .then() , , - , , .

, :

 / `rp`-   request-promise. rp('https://api.example.com/endpoint1').then(function(data) { // 
 }); 

, async / await :

 // `rp`-   request-promise. var response = await rp('https://api.example.com/endpoint1'); 

▍


async / await . , try / catch .

, . , .catch() , try / catch :

 function loadData() {   try { //   .       getJSON().then(function(response) {           var parsed = JSON.parse(response);           console.log(parsed);       }).catch(function(e) { //              console.log(e);       });   } catch(e) {       console.log(e);   } } 

async / await :

 async function loadData() {   try {       var data = JSON.parse(await getJSON());       console.log(data);   } catch(e) {       console.log(e);   } } 

▍


async / await , . — , :

 function loadData() { return getJSON()   .then(function(response) {     if (response.needsAnotherRequest) {       return makeAnotherRequest(response)         .then(function(anotherResponse) {           console.log(anotherResponse)           return anotherResponse         })     } else {       console.log(response)       return response     }   }) } 

— async / await :

 async function loadData() { var response = await getJSON(); if (response.needsAnotherRequest) {   var anotherResponse = await makeAnotherRequest(response);   console.log(anotherResponse)   return anotherResponse } else {   console.log(response);   return response;    } } 

▍


async / await , , , , . :

 function loadData() { return callAPromise()   .then(callback1)   .then(callback2)   .then(callback3)   .then(() => {     throw new Error("boom");   }) } loadData() .catch(function(e) {   console.log(err); // Error: boom at callAPromise.then.then.then.then (index.js:8:13) }); 

— , async / await :

 async function loadData() { await callAPromise1() await callAPromise2() await callAPromise3() await callAPromise4() await callAPromise5() throw new Error("boom"); } loadData() .catch(function(e) {   console.log(err);   //    // Error: boom at loadData (index.js:7:9) }); 

▍


, , — . , .then «step-over», .then , «» . async / await , await , — .

たずめ


, . , SessionStack , -. , DOM, , JavaScript, , , .

- . , , , , . . , , , .

, . JavaScript, , . , , , .

芪愛なる読者 JS-. , - . — async / await . , , , . ( ) a sync / await .

Source: https://habr.com/ru/post/J340508/


All Articles