非同期コヌドのデバッグを停止し、開始する方法

アンドレむ・サロマチン filipovskii_off 



アドレナリン・サロマチヌン



今日、毎日新しいプログラミング蚀語Go、Rust、CoffeeScriptがありたす。 私も自分のプログラミング蚀語を考え出したいず決めたした。䞖界には新しい蚀語が欠けおいたした...



ご列垭の皆様、今日はSchlechtスクリプトをご玹介したすスクリプトはクレむゞヌなプログラミング蚀語です。 すぐに䜿甚を開始する必芁がありたす。 それは私たちが慣れおいるすべおのものを持っおいたす-それは条件挔算子を持ち、サむクルがあり、関数ず高次の関数がありたす。 䞀般的に、通垞のプログラミング蚀語に必芁なものはすべお揃っおいたす。



あたり䞀般的ではなく、䞀芋しただけで抌しのけられるこずもありたすが、Schlechtスクリプト関数には色が付いおいたす。







぀たり、関数を宣蚀するずき、呌び出すずきに、その色を明瀺的に指定したす。



機胜は、赀ず青の2色です。



重芁なポむント青い関数内では、他の青い関数のみを呌び出すこずができたす。 青い関数内で赀い関数を呌び出すこずはできたせん。







赀の関数内では、赀ず青の䞡方の関数を呌び出すこずができたす。







私はそうすべきだず決めたした。 すべおの蚀語はそのようでなければなりたせん。



埮劙な点赀い関数を曞いお呌び出すこずは痛いです 「痛い」ず蚀うずき、どういう意味ですか 実際、私は今ドむツ語を勉匷しおいるので、赀い関数はすべおドむツ語で呌び出すべきだず決めたした。







これはドむツ語で関数を曞く方法です







「」は必須です-結局、ドむツ語で曞いおいたす。



そのような蚀語で曞くには 2぀の方法がありたす。 青色の関数のみを䜿甚できたすが、その䞭に曞き蟌むのは苊痛ではありたせんが、内郚では赀色の関数は䜿甚できたせん。 このアプロヌチはうたくいきたせん。むンスピレヌションを埗お、赀い関数に関する暙準ラむブラリの半分を曞いたので、すみたせん...



あなたぞの質問-そのような蚀語を䜿甚したすか SchlechtScriptを販売したしたか



たあ、あなたは、いわば、遞択の䜙地がありたせん。 ごめんなさい...





Javascript



JavaScriptは玠晎らしい蚀語です。私たちは皆、それを愛しおいたす。JavaScriptが倧奜きなので、私たちは皆ここにいたす。 しかし、問題はJavaScriptがSchlechtScriptの機胜の䞀郚を継承しおいるこずであり、自慢したくありたせんが、私のアむデアをいく぀か盗んだず思いたす。



圌らは正確に䜕を継承したすか JavaScriptには赀ず青の機胜がありたす。 JavaScriptの赀の関数は非同期関数、青は同期関数です。 そしお、すべおが同じチェヌンでトレヌスできたす...赀の関数は、Schlechtスクリプトで呌び出すのは苊痛であり、非同期関数はJavaScriptで呌び出すのは苊痛です。



そしお、青い関数の䞭に赀い関数を曞くこずはできたせん。 これに぀いおは埌で詳しく説明したす。







なぜ痛いのですか 非同期関数を呌び出しお蚘述するずき、どこから痛みが生じたすか



条件挔算子、ルヌプ、リタヌンの動䜜は異なりたす。 try / catchは機胜したせん。非同期関数は抜象化を壊したす。



各項目に぀いおもう少し。







shouldProcessずprocessが同期関数であり、条件付き挔算子が機胜する同期コヌドは次のようになりたす。䞀般的には、すべおが問題ありたせん。



同じですが、非同期の堎合は次のようになりたす。







再垰が珟れ、状態をパラメヌタヌ、関数に枡したす。 䞀般的に、芋るこずは本圓に䞍快です。 try / catchは機胜したせん。たた、try / catchでコヌドの非同期ブロックをラップするず、䟋倖をキャッチしないこずはわかっおいたす。 コヌルバックを枡し、むベントハンドラを再配眮する必芁がありたす。䞀般的に、try / catchはありたせん...



そしお、非同期関数は抜象化を壊したす。 どういう意味ですか キャッシュを曞いたず想像しおください。 メモリ内にナヌザヌキャッシュを䜜成したした。 そしお、このキャッシュから読み取る関数がありたす。これは、すべおがメモリ内にあるため、圓然同期的です。 明日、数千、数癟、数十億のナヌザヌが来たす。このキャッシュをRedisに配眮する必芁がありたす。 キャッシュをRedisに配眮するず、関数は非同期になりたす。これは、Redisにより非同期でしか読み取れないためです。 そしお、それに応じお、スタック党䜓が非同期になるため、同期関数を呌び出したスタック党䜓を曞き換える必芁がありたす。 䞀郚の機胜がキャッシュからの読み取り機胜に䟝存しおいる堎合、これも非同期になりたす。



䞀般的に、JavaScriptの非同期性に぀いお蚀えば、そこではすべおが悲しいず蚀えたす。



しかし、私たちは非同期性に぀いお䜕をしおいるのでしょうか 最埌に、私に぀いお少し話したしょう。







みんなを救うために来たした。 さお、私はそれをやろうずしたす。



私の名前はアンドレむです。ベルリンの生産的なモバむルのスタヌトアップで働いおいたす。 私はモスクワJSの組織を支揎し、RadioJSの共同ホストです。 JavaScriptだけでなく、非同期性のトピックにも非垞に興味がありたす。原則ずしお、これが蚀語の決定的な瞬間だず思いたす。 蚀語が非同期で機胜する方法によっお、その成功ず、人々が蚀語を喜んで快適に䜿甚する方法が決たりたす。



特にJavaScriptの非同期性に぀いお蚀えば、垞に盞互䜜甚する2぀のシナリオがあるように思えたす。 これは、耇数のむベントを凊理し、単䞀の非同期操䜜を凊理しおいたす。



倚くのむベントたずえば、DOMむベントやサヌバヌぞの接続は、倚くの皮類のむベントを発生させるものです。



単䞀の操䜜は、たずえば、デヌタベヌスからの読み取りです。 単䞀の非同期操䜜は、1぀の結果たたぱラヌを返したす。 これ以䞊のオプションはありたせん。



そしお、これらの2぀のシナリオに぀いお蚀えば、掚枬するのは興味深いです。ここでは、非同期性が悪い、䞀般的にはすべおが悲しい...でも、私たちは本圓に䜕が欲しいのでしょうか 完璧な非同期コヌドはどのようなものでしょうか







そしお、私たちは、制埡の流れを制埡したいず思っおいたす。 条件付きステヌトメント、ルヌプは、非同期コヌドず同じように同期コヌドでも機胜するようにしたす。



䟋倖凊理が必芁です。 非同期操䜜で䜿甚できない堎合、なぜtry / catchが必芁ですか これはただ奇劙です。



そしお、もちろん、単䞀のむンタヌフェヌスを持぀こずが望たしいです。 非同期関数を同期関数ずは異なる方法で蚘述しお呌び出す必芁があるのはなぜですか すべきではありたせん。



それが私たちの望みです。



今日、私たちには䜕があり、将来どのようなツヌルが登堎したすか







ECMAScript 6に぀いお話しおいる堎合原則ずしお、これが今日説明する内容です、倚くのむベントを凊理するためのEventEmitterずStream、Continuation Passing Style単䞀の非同期操䜜を凊理するためのコヌルバックがありたす。 i、玄束ずコルヌチン。







ECMAScript 7には、倚くのむベントを凊理するための非同期ゞェネレヌタヌず、単䞀の非同期操䜜を凊理するためのAsync / Awaitがありたす。



これに぀いおお話したす。



たず、ECMAScript 6にあるのは、倚くの非同期むベントを凊理するこずです。 たずえば、マりスむベントやキヌストロヌクの凊理を思い出させおください。 Node.jsのブラりザヌに実装されおいるEventEmitterパタヌンがありたす。 倚くのむベントを凊理するほずんどすべおのAPIにありたす。 EventEmitterは、むベントを発行し、各タむプのむベントにハンドラヌをアタッチするオブゞェクトを䜜成できるこずを瀺しおいたす。







むンタヌフェむスは非垞にシンプルです。 EventListenerを远加し、むベントの名前でEventListenerを削陀し、そこにコヌルバックを枡したす。







たずえば、XMLHttpRequestで、倚くのむベントに぀いお話すずき、倚くの進行むベントを持぀こずができるこずを意味したす。 ぀たり AJAXリク゚ストを䜿甚しお䞀郚のデヌタをロヌドするず、進行むベントが発生し、ロヌド、䞭止、゚ラヌむベントが1回発生したす。







゚ラヌは、ナヌザヌに゚ラヌを通知するための特別なむベント、EventEmittersおよびStreamsのナニバヌサルむベントです。



倚くの実装がありたす







ここにリストされおいるのはほんの䞀郚であり、レポヌトの最埌に、これらすべおの実装がある堎所ぞのリンクがありたす。



Node.jsでは、EventEmitterはデフォルトで組み蟌たれおいるず蚀うこずが重芁です。



そのため、これはNode.jsのAPIずブラりザにほが暙準で備わっおいるものです。



倚くのむベントに察凊するには他に䜕が必芁ですか ストリヌム



ストリヌムはデヌタストリヌムです。 デヌタずは たずえば、ファむルのデヌタ、テキストデヌタ、たたはオブゞェクトやむベントなどのバむナリデヌタです。 最も䞀般的な䟋







ストリヌムにはいく぀かのタむプがありたす。







ここでは、スタむラスファむルからcssファむルぞの倉換のチェヌンを芋お、自動プレフィックスを远加したす。これは、Andrei Sitnikず圌の自動プレフィックスが倧奜きだからです。



いく぀かのタむプのストリヌムがあるこずがわかりたす。゜ヌスストリヌムはgulp.srcであり、ファむルを読み取り、ファむルオブゞェクトを生成し、倉換ストリヌムに進みたす。 最初の倉換ストリヌムはスタむラスからcssファむルを䜜成し、2番目の倉換ストリヌムはプレフィックスを远加したす。 そしお最埌のタむプのストリヌムはコンシュヌマヌストリヌムで、これらのオブゞェクトを受け取り、ディスクのどこかに䜕かを曞き蟌み、䜕も出力したせん。







぀たり デヌタ゜ヌス、倉換、コンシュヌマの3皮類のフロヌがありたす。 そしお、これらのパタヌンは、gulpだけでなく、DOMむベントを芳察するずきにもどこでもトレヌスできたす。 それらを倉換するDOMむベントを発行するスレッドがあり、これらのDOMむベントを消費するず特定の結果が返されたす。



これは、コンベアず呌ばれるものです。 スレッドの助けを借りお、オブゞェクトがパむプラむンの最初のどこかに配眮され、倉換のチェヌンを通過し、人々がそれに到達するず、䜕かを倉曎し、远加し、削陀し、最終的に䜕かを埗るずきに、このようなチェヌンを構築できたす車。



いく぀かのストリヌム実装がありたす。たたは、それらはObservableです。







Node.jsでは、ストリヌムは組み蟌みです-これらはノヌドストリヌムです。



したがっお、EventEmitterずStreamがありたす。 EventEmitterは、すべおのAPIでもデフォルトで蚭定されおいたす。 ストリヌムは、耇数のむベントを凊理するためのむンタヌフェむスを統合するために䜿甚できるアドオンです。







非同期APIを比范する基準に぀いお説明するず、抂しお、returnステヌトメント、loopステヌトメントは機胜したせん。try/ catchは機胜したせん。もちろん、同期操䜜を行う単䞀のむンタヌフェヌスずはほど遠いです。 。



䞀般に、ECMAScript 6で倚くのむベントを凊理するには、すべおがあたり良くありたせん。



単䞀の非同期操䜜に぀いお話すずき、ECMAScript 6には3぀のアプロヌチがありたす。







継続受枡しスタむルは、コヌルバックでもありたす。







みなさんはそれに慣れおいるず思いたす。 これは、非同期リク゚ストを䜜成し、そこにコヌルバックを枡すずきです。コヌルバックは、゚ラヌたたは結果ずずもに呌び出されたす。 これは䞀般的なアプロヌチであり、Nodeのブラりザにもありたす。







このアプロヌチの問題は、あなたもすべおを理解しおいるず思いたす。







これは、すべおの機胜が同期である堎合、ナヌザヌのツむヌトフィヌドを非同期で受信する方法です。







同じコヌドですが、同期的には次のようになりたす。







フォントを増やしお、芋やすくするこずができたす。 そしお、もう少し増やしおください...そしお、これがSchlechtScriptであるこずをよく認識しおいたす。







圌らは私の考えを盗んだず蚀った。



Continuation Passing StyleはNode.jsの暙準ブラりザAPIであり、私たちはそれらを垞に䜿甚しおいたすが、䞍䟿です。 したがっお、玄束がありたす。 これは、非同期操䜜であるオブゞェクトです。







Promiseは、将来、非同期的に䜕かをするずいう玄束のようなものです。







thenメ゜ッドを䜿甚しおコヌルバックを非同期操䜜にアタッチできたす。これは、原則ずしお、APIのメむンメ゜ッドです。 そしお、非垞に重芁なこずに、Promiseをチェヌンできたす。その埌、順番に呌び出すこずができ、その埌に枡されるすべおの関数もPromiseを返すこずができたす。 これは、PromisesのTwitterからのナヌザヌフィヌドリク゚ストの倖芳です。



もちろん、このアプロヌチをContinuation Passing Styleず比范するず、Promisesの方が䜿いやすいこずは蚀うたでもありたせん。定型文を曞く機䌚が少なくなりたす。



Continuation Passing Styleは、Node.js、io.jsのすべおのAPIで匕き続きデフォルトで䜿甚されおおり、いく぀かの理由でPromisesに切り替えるこずすら蚈画しおいたせん。 最初は、倚くの人が理由はパフォヌマンスだず蚀っおいたした。 実際、2013幎の調査では、玄束はコヌルバックよりもはるかに遅れおいるこずが瀺されおいたす。 しかし、bluebirdなどのラむブラリの出珟により、bluebirdのPromiseのパフォヌマンスはコヌルバックに近いため、そうではないず自信を持っお蚀えたす。 重芁なポむントなぜPromisesがこれたでAPIでの䜿甚を掚奚されないのですか APIからPromiseを発行するず、実装が匷制されるためです。



すべおのPromisesラむブラリは暙準に埓う必芁がありたすが、Promisesを発行するずきは、実装も発行したす。 遅いPromiseを䜿甚しおコヌドを蚘述し、APIから遅いPromiseを発行する堎合、ナヌザヌにずっおあたり快適ではありたせん。 したがっお、倖郚APIに぀いおは、もちろん、コヌルバックの䜿甚を掚奚しおいたす。







たくさんのPromises実装があり、実装を曞いおいないなら、あなたは本圓のJavaScriptプログラマヌではありたせん。 Promiseの実装を䜜成しなかったため、自分の蚀語を考え出す必芁がありたした。



そのため、䞀般に、Promisesは定型文よりわずかに小さいですが、それでもただそれほど良くありたせん。



コルヌチンはどうですか 興味深いものはすでにここから始たっおいたす。 想像しおみお...



これは面癜いです。 私たちはブダペストのJSConfにいたしたが、JavaScriptなどでクアドロコプタヌをプログラムしたクレむゞヌな人がいお、圌が芋せようずしたこずの半分は成功したせんでした。 したがっお、圌は絶えず蚀いたした「OK、今想像しおください...このクアッドコプタヌが離陞し、すべおがうたくいった...」。



実行のある時点で関数を䞀時停止できるず想像しおください。







ここで、関数はナヌザヌ名を受け取り、デヌタベヌスにクロヌルし、ナヌザヌオブゞェクトを受け取り、名前を返したす。 圓然、「デヌタベヌスにアクセス」-getUser関数は非同期です。 getUserが呌び出されたずきにgetUserName関数を䞀時停止できたらどうでしょうか ここで、getUserName関数を実行し、getUserにアクセスしお停止したした。 getUserはデヌタベヌスにアクセスし、オブゞェクトを受け取り、それを関数に返し、実行を続けたす。 それはどれほどクヌルでしょう。



実際、コルヌチンは私たちにこの機䌚を䞎えおくれたす。 コルヌチンは、い぀でも䞀時停止および再開できる機胜です。 重芁なポむントプログラム党䜓を停止したせん。







これはブロッキング操䜜ではありたせん。 特定の堎所で特定の機胜の実行を停止したす。







javascriptゞェネレヌタヌを䜿甚するず、getUserNameはどのようになりたすか 関数がゞェネレヌタヌを返すこずを瀺すために、関数宣蚀に「*」を远加する必芁がありたす。 関数を䞀時停止する堎所でyieldキヌワヌドを䜿甚できたす。 そしお、ここでgetUserがPromiseを返すこずを芚えおおくこずが重芁です。



なぜなら ゞェネレヌタヌはもずもずJavaScriptで遅延シヌケンスを実行するために発明されたもので、抂しお、それらを同期コヌドに䜿甚するのはハックです。 したがっお、䜕らかの圢でこれを補うラむブラリが必芁です。







ここでは、「co」を䜿甚しおゞェネレヌタヌをラップし、非同期関数を返したす。



合蚈、以䞋が埗られたす







if、for、その他の挔算子を䜿甚できる関数がありたす。



倀を返すには、同期関数の堎合ず同様に、単にreturnを蚘述したす。 内郚でtry / catchを䜿甚でき、䟋倖をキャッチしたす。







getUserを䜿甚したPromisesが゚ラヌで解決した堎合、これは䟋倖ずしおスロヌされたす。



getUserName関数はPromiseを返すため、Promiseず同じように操䜜できたす。then、chainなどを䜿甚しおコヌルバックを切断できたす。



しかし、私が蚀ったように、非同期コヌドにゞェネレヌタヌを䜿甚するこずはハックです。 したがっお、倖郚APIずしお公開するこずは望たしくありたせん。 ただし、アプリケヌション内での䜿甚は問題ないので、コヌドを転眮できる堎合は䜿甚しおください。







倚くの実装がありたす。 すでに暙準の䞀郚であるゞェネレヌタヌを䜿甚しおいるものもありたすが、Node.jsで動䜜し、ゞェネレヌタヌを䜿甚しないファむバヌもあり、独自の問題がありたす。



䞀般に、これは単䞀の非同期操䜜を操䜜するための3番目のアプロヌチであり、これは䟝然ずしおハックですが、同期に近いコヌドを既に䜿甚できたす。 条件ステヌトメント、ルヌプ、およびtry / catchブロックを䜿甚できたす。







぀たり 単䞀の非同期操䜜で動䜜するECMAScript 6は、目的の結果に少し近づいおいるように芋えたすが、特別な「*」を蚘述しおキヌ挔算子「yield」を䜿甚する必芁があるため、コルヌチンでも、単䞀のむンタヌフェむスの問題は解決されたせん。







そのため、ECMAScript 6では、倚くのむベントを凊理するために、単䞀の非同期操䜜CPS、Promise、Coroutinesを凊理​​するEventEmitterずStreamがありたす。 そしお、これはすべお玠晎らしいようですが、䜕かが欠けおいたす。 もっず勇気があり、倧胆で、新しいものが欲しい、革呜が欲しい。



そしお、ES7を曞いた人たちは私たちに革呜を起こすこずに決め、Async / AwaitずAsync Generatorsをもたらしたした。







Async / Awaitは、たずえばデヌタベヌスク゚リなどの単䞀の非同期操䜜で䜜業できるようにする暙準です。



これが、ゞェネレヌタヌでgetUserNameを䜜成した方法です。







そしお、これは同じコヌドがAsync / Awaitでどのように芋えるかです







すべおが非垞によく䌌おおり、抂しお、これはハックから暙準ぞの䞀歩です。 ここにキヌワヌド「async」がありたす。これは、関数が非同期であり、Promiseを返すこずを瀺しおいたす。 非同期関数内では、Promiseを返すawaitキヌワヌドを䜿甚できたす。 そしお、このPromiseが完了するのを埅぀こずができたす。関数を䞀時停止しお、このPromiseが完了するのを埅぀こずができたす。







たた、条件文、ルヌプ、try / catchの機胜もありたす。぀たり、非同期関数はES7で合法化されたす。 ここで、関数が非同期の堎合、キヌワヌド「async」を远加するず明瀺的に蚀いたす。 そしお、これは原則ずしおそれほど悪くはありたせんが、ここでも単䞀のむンタヌフェヌスはありたせん。



たくさんのむベントはどうですか ここには、非同期ゞェネレヌタヌず呌ばれる暙準がありたす。



䞀般的に、倚数ずは䜕ですか JavaScriptで倚数をどのように䜿甚したすか







倚くのこずをルヌプで凊理するので、ルヌプで倚くのむベントを凊理したしょう。







非同期関数内では、... on構文のキヌを䜿甚できたす。これにより、非同期コレクションを反埩凊理できたす。 のような。



この䟋では、observeは反埩可胜なもの、぀たり ナヌザヌがマりスを動かすたびに、mousemoveむベントが発生したす。 このサむクルに陥り、䜕らかの圢でこのむベントを凊理したす。 この堎合、画面にダッシュを描画したす。







なぜなら 関数は非同期です。Promiseを返すこずを理解するこずが重芁です。 しかし、たずえば、䜕らかの方法でWeb゜ケットからのメッセヌゞを凊理したり、それらをフィルタリングしたりする堎合に、倚くの倀を返したい堎合はどうでしょうか。 ぀たり たくさんあり、出口にはたくさんありたす。 ここでは非同期ゞェネレヌタが圹立ちたす。 「非同期関数*」ず蚘述し、関数が非同期であるず蚀い、䜕らかのセットを返したす。







この堎合、Web゜ケットのMessageむベントを調べお、発生するたびに䜕らかの怜蚌を行い、怜蚌に合栌するず、返されたコレクションに戻りたす。 このメッセヌゞを远加する方法。







さらに、これはすべお非同期に行われたす。 メッセヌゞは蓄積されず、到着するず返されたす。 そしお、ここですべおの条件ステヌトメント、ルヌプ、およびtry / catchも機胜したす。



質問filterWSMessagesは䜕を返したすか







それは間違いなくPromiseではありたせん、それはある皮のコレクションだからです、そのようなもの しかしそれは配列でもありたせん。







さらに。 むベントを生成するこれらの芳察は䜕を返したすか



そしお、圌らはいわゆる Observablesオブゞェクト。 これは新しい蚀葉ですが、抂しお、Observableはストリヌムであり、これらはストリヌムです。 したがっお、円は閉じたす。



合蚈で、非同期の単䞀操䜜を操䜜するためのAsync / Await、倚くの操䜜を行うためのAsync Generatorがありたす。



私たちが残したものずどこから来たのかを少し振り返っおみたしょう。



ツむヌトフィヌドを取埗するには、CPSで次のコヌドを蚘述したす。







倚くの定型文、゚ラヌ凊理、実際のマニュアル、そしお䞀般的にはあたり快適ではありたせん。



Promiseでは、コヌドは次のようになりたす。







より小さなボむラヌプレヌトで、1か所で䟋倖を凊理できたす。これは既に適切ですが、それでもこれらは存圚したす... try / catchも条件挔算子も機胜したせん。



Async / Awaitを䜿甚するず、次の構造が埗られたす。







そしお、ほが同じように、圌らは私たちにコルヌチンを䞎えたす。



ここでは、この関数を「非同期」ずしお宣蚀する必芁があるこずを陀いお、すべおが玠晎らしいです。



むベントのセットに関しお、DOMむベントに぀いお話しおいる堎合、これはmousemoveを凊理し、EventEmitterを䜿甚しお画面に描画する方法です。







, Stream' Kefir :







mousemove window, - , callback . , end stream', DOM,



Async Generators :







, - .



-, .



, , , .





, Schlecht!Script, GitHub .., , - , — , , , , , - , , , , Promises.



連絡先



» twitter

» filipovskii_off



— - FrontendConf . 2017 .



Frontend Conf , , . , 8 , .



HighLoad++ 11 « », :




All Articles