玄束は宝石アヌトです

この蚘事は、ゞュ゚リヌの人気が高たっおいるために仕事を蟞め、以前の仕事に少し手を加えなければならなかった宝石商のために曞かれおいたす。



プログラミングの新しい抂念に出くわすたびに、それが珟実の䞖界に反映されおいるこずを芋぀けようずしたす。玄束-それらは合意であり、それは䜕ですか 誰かが将来誰かのために䜕かをするプロセスの説明ずしお、玄束を远い越す自由を取りたす。 次に、この説明を広矩に圢匏化しようずしたす。 私たちの抜象的な想像力では、3぀のオブゞェクトのセットを䞀床に衚瀺できたす。1぀目は玄束するもの、2぀目は玄束するもの、3぀目は玄束するものです。 すでに耇雑な3セットのオブゞェクト、それらはどのような関係に䜜甚したすか、どのように接続されたすか いく぀かの質問。 単玔化のために最初にできるこずは、最初のセットず3番目のセットを組み合わせるこずです。それらの性質は同じであるため、人、コンピュヌティングノヌドなどになる可胜性がありたす....怜蚎䞭の特定の技術環境のフレヌムワヌク内で、Node Js bundles、Q libraryナナむテッドセットはそれ自䜓をロックしたす。 実際、私たちのケヌスでは、コヌド内で䜕かが実行されたず蚀ったずきに自分自身に玄束をしたす。 実際には、䞀床に2セットの堎所が存圚する可胜性があるタスクが存圚したす。 たずえば、共同蚈算を行う盞互䜜甚する゜フトりェアノヌドから環境を想像するこずは簡単であり、2぀のセットはたったくありたせん。 しかし、䟋ずしおQラむブラリを䜿甚しおNode.Jsのpromiseを芋おいきたす。



したがっお、できるこずは、いく぀かのタスクセットを完了するこずを玄束するこずだけです。 さお、倚くのオブゞェクトがあるずすぐに、私たちのケヌスでは倚くの問題があるので、数孊者が行うように、このセットにすぐに関係を導入できたす。 そしお、関係の1぀がすぐに衚瀺されたす。これは、私たちの堎合に適した方法です。順序の関係です。 そしおすぐにわかるように、この関係はpromiseオブゞェクトの「then」メ゜ッドによっお実珟されたす。



珟実の䞖界に戻っお、プログラムマネヌゞャヌに次のような玄束をするこずは可胜ですか

「サヌシャ、よく聞いおください、初期化モゞュヌルを䜜成した埌、ブヌトモゞュヌルを䜜成したすか」

サヌシャはそのような玄束に満足せず、空䞭にぶら䞋がっおいる関係の連鎖ではなく、䜕かに基づいお構築する必芁があるこずは明らかです。 次に、玄束を芋おみたしょう。自分のために特定の未来を自動的に構築するず玄束したずき、行動を具䜓的な未来に投圱し、倩才はそれを氞遠に投圱したす、蚈算の抂念も倉化しおいるずいう理由だけで、近い将来を考慮したす。 そしお、ここで新しい疑問が生じたすが、Node Jsの特定の未来をどのように想像したすか。



Node.jsは、非ブロッキングI / Oを䜿甚したむベント指向および非同期たたはリアクティブプログラミングに基づいおいたす-これはWikiから取埗したものです。 玄束の点で、これが私たちにずっお䜕を意味するのか。 「ティック」コントロヌルがスクリプトに転送されるたびに矢印が付いた時蚈を想像しおください。「いいね」コントロヌルがノヌドに転送されるず、ノヌドが「so」フェヌズでのみ動䜜するこずを意味したせん。そのため、「私たちは、圌によっお割り圓おられた非同期I / Oタスクの問題に関する圌の掻動の結果を圌が私たちに通知するず仮定したす。 未来を構築するための最初の詊みを行い、それを再びティック間に分割したした。たた、倚くのティックの順序関係を再床玹介したす。 どうやらそこから抜け出す方法はないようです。そしお、因果関係なくしお人々がどのようにプログラムするのかわからないこずに感謝したす。 Tick-to-Tackモデルに目を向けるず、将来のモデルを単玔化し、玄束をより実珟するこずにより、責任範囲を狭めたす。

今、私たちは将来、垞に「ティック」フェヌズがあるこずを知っおいたす。私たちはこの未来の䞻暩ホストです。 制埡ノヌドを提䟛するこずで、タスクをロヌドするこずが期埅され、通垞はこれを行いたす。 これを行う方法、最初から、開始スクリプトがあり、ティックフェヌズで実行を開始したす。実行の結果は、基本ノヌドAPIによっお圢成されるタスク、たずえばfs.readFile(filename, [options], callback)



になりたすタスクはありたせん。プログラムは䜜業を終了したす。 タスクが完了するずすぐに、ノヌドは次の「ティック」フェヌズでコヌルバックの実行を蚈画し、それに制埡を移したすコヌルバック。 そしお、その䞭に他のNodeタスクを蚭定したす。 たた、非同期API党䜓がNodeのコヌルバックに実装されおいるため、説明するタスクはそれらにありたす。

そしお、この状況は「コヌルバック関数の地獄」ず呌ばれおいたす。 ずころで、フォヌラムで特定の問題を議論するずき、人々はこの地獄ず非垞に良い友達です。なぜなら、フォヌラムでのメッセヌゞ亀換のスタむルはこのスタむルのすべおの基準を満たしおいるからです。 そしお、なぜこれがコヌドの問題になる可胜性があるのでしょうか、そうです、プログラマヌはコヌドの長さに察しおのみ支払われたす、氎平方向に拡匵するために誰も支払わないか、そうでないかもしれたせん。 もちろん、圌らはコヌディングスタむルの芳点からコヌルバック地獄に぀いお曞いおおり、そのようなスタむルの背埌に隠れおいるかもしれないものをわずかに省略しおいたす。



この状況を芋おみたしょう。



 a(arg1, function() { var x1; b(arg2, function() { var x2; setInterval(function Task() { console.log('tik'); }, interval); }); })
      
      







ここでは、䜕かを行う間隔間隔でNodeタスクを間隔で蚭定するず、呌び出しツリヌのブランチ党䜓はチェヌン、クロヌゞャヌずも呌ばれ、タスクが存続しお実行されおいる限りメモリ内に存圚し続けたすが、䜿甚されない堎合がありたす䞊で説明した倉数ず匕数x1、x2、arg1、arg2 ...そしお、これは、そのようなネストされたタスクを曞く䟡倀があるかどうか、すでに疑問に思っおいたす。 たずえば、このケヌスでは、タスクは単に「tick」ずいう単語を衚瀺する堎合がありたす。



しかし、これらはjavascriptの問題であり、その性質は、すべおが実行、解釈の段階で発生する超動的蚀語であるため、もちろんコヌドの構造は実行のセマンティクスを反映しおいたす。 静的なコンパむル蚀語では、関数倉数ず匕数はスタックたたはレゞスタヌに配眮され、関数が䜜業を終了するずすぐに解攟され、そのような問題は発生したせん。 そしお、無駄なメモリ消費やパフォヌマンスの䜎䞋に぀ながる可胜性がある状況がある堎合は、それらを回避する方が良いのですが、どのように



そしお、ここに玄束の抂念があり、それに続いお、たずえば䞊蚘のような状況を回避するこずができたす。 もう少し䞊に、私たちは未来の抂芁を説明し始め、それを2぀のフェヌズに分割し、そのフェヌズでティックを描画するか、Node jsをレンダリングするタスクを提䟛できるこずに気付きたした。 しかし、コヌドを連続しお2回続けお蚘述するずどうなりたすか。䞊蚘のコヌドを参照しおください。 確かに、特定の間隔でタスクは2回実行されたすが、どのような順序で実行されたすか しかし、誰もこれを明確に教えおくれたせん。特定の順序を期埅するこずしかできたせんが、保蚌されおいるわけではありたせん。 今、私たちはさたざたなタスクの順序関係を想像力に導入し、その履行を芁求するすべおの暩利ず玄束の抂念を持っおいるこずを思い出したす。そしお、そのような暩利を䞎えるず、タスクをチェヌンにリンクし、実行するこずを芁求できたすひず぀ず぀。 しかし、それでは䟋を挙げないで、少し違うこずから始めたしょう。 そしお、javascriptでの実装の芳点からの玄束は䜕でしょうか。 たた、javascriptの䞀郚ずしお衚瀺するオブゞェクトタスクの数。 たくさんのタスクに぀いお、「私たちが玄束するもののような」倚くのオブゞェクトに぀いお私が暗黙のうちに話し始めおから、それを倚くの玄束に倉えたこずに気づかなかった。 このセットのオブゞェクトにいく぀かの二重性が芋られたす。 そのため、ここでは埐々に特定の実装に移行しおいたす。

プログラミング蚀語のフレヌムワヌク内で問題のセットの順序関係を実珟するためには、このセットの各芁玠に二重の性質を䞎えなければなりたせん。これは玄束でもありタスクでもありたす。 ぀たり ここで、タスクは実行のための呜什のセットであり、実行されるタむミングはわかりたせん。玄束は正確に順序関係自䜓の原因であり、タスクの実行が開始される瞬間を決定するメカニズムは隠されおいたす。 玄束は、タスクを遂行するための条件が芏定されおいる玙の契玄などの具䜓的なものであり、タスクはプロセスであり、無圢の䜕かであり、その二重性は䞀察の空間玄束-時間タスクず比范できたす。 スペヌスをメモリに関連付け、時間をコヌド、指瀺に関連付けるこずができたす。 ただし、javascriptにはこの二重性がネむティブに含たれおおり、関数はオブゞェクトメ゜ッドだけでなくプロパティも持぀こずができたす。 欲しいものを遞択しおください。



Qラむブラリの開発者は、最適なオプションはネむティブjavascript関数をタスクに割り圓お、オブゞェクトをpromiseに割り圓おるこずであるず刀断したした。 タスクを゚ンコヌドする単玔な関数を、ある抂念のフレヌムワヌク内のタスクにするにはどうすればよいのでしょうかそれをすべおず区別するために、どうすればよいでしょうか Qがタスクから通垞の機胜を分離できる䞀方で、この機胜が存圚しない堎合にpromiseテクノロゞヌを適甚できるように、圌女には䜕らかの分類機胜が必芁であるこずは明らかです。 Javascriptには十分な分類オプションがありたす。 しかし、開発者は関数ラッパヌメカニズムを䜿甚するこずにしたした。これは、機胜的javascriptの性質に非垞に自然に矎しく適合したす。 ぀たり ラむブラリナヌザヌに䌝え、関数を蚘述し、特別なラッパヌラむブラリ関数に枡したす。コンテキストではそれらをタスクず芋なしたす。 ぀たり 実際、私たちは䞀般に、玄束の抂念で䜜業を開始するために特別なこずは䜕もできたせん。

぀たり、2぀のタスクの順序関係を保蚌するために、次のように蚘述できたす。



 Q.fcall(function task1() {
}).then(function task2(){
});
      
      







ここでは、fcall、次にラッパヌ関数のみがタスク1ずタスク2を取埗し、タスクになりたす。関数に察しおは䜕もしたせん。これらの関数は、䞊蚘のコヌドを実行する過皋で隠しプロパティを蓄積したせん。 このコヌドから埗られるものですが、task1のtask2の実行が保蚌されたすが、すでに次の「ティック」に含たれおいたす。 タスクの実行ずは、関数の実行、぀たり 関数内でreturn匏たたはその最埌に到達したずきyieldステヌトメント、ここでは芋逃したす。 関数task1およびtask2に非同期コヌルバックを䜿甚したAPI呌び出しがある堎合、実行シヌケンスはコヌドによっお保蚌されたせん。䞊蚘を参照しおください。これに察しお特別なアクションを実行しない堎合、コヌルバックは単独で実行されたす。 次に、そのような構造が必芁な理由を尋ねるず、単に曞くこずができたす



 task1(); task2();
      
      







はい、可胜ですが、たずえば、最初の1぀が内郚で非同期APIにアクセスし、2぀目がそうでない堎合、task1コヌドで順序を蚭定したす。 task2; 内郚で䜕もせずに倱敗したす。 別の䟋では、タスクA、B、Cのようなシヌケンスがありたす。AずCは非同期で、Bは同期ですQ.fcall(A).then(B).then(C)



、および関数Bで埌述するように、特別なpromiseオブゞェクトを返す必芁はありたせん。Qラむブラリがこれを行いたす。



私たちは今、玄束に目を向けたす、そしお、圌らがここに珟れる堎所、これらの玙片は、玙片なしで蚀うように、私の兄匟ず私は双子ではありたせん。 建蚭の腞では、䞊蚘を参照しお、玄束が生たれ、その実装の結果が玄束になりたす。 内郚でこれがどのように行われ、Qラむブラリが実装されるずしばらく攟眮されたすが、最も重芁なこずは、Q関数のモナドfcall、thenなどず呌ばれるこずがある䞀連の呌び出しがほずんど垞に玄束を生成するこずを理解するこずです他のモナド間のリンクずしお。 䜜成されたものの腞には状況を完党に制埡するのに必ずしも十分ではないずいう説明、そしおもちろん、ラむブラリは玄束を明瀺的に䜜成するためのメカニズムを提䟛したす。



それなしで行うこずは可胜ですかなぜそれが必芁ですか 同期タスクのみを䜿甚する堎合、明確な玄束を䜜成する必芁はありたせん。 非同期ノヌドJS APIを䜿甚する堎合、Qラむブラリヌには、Promiseを暗黙的に䜜成するラッピング関数がありたす。 非同期タスクで䜜業する堎合でも、明瀺的にプロミスを䜜成するためのメカニズムを䜿甚しない理論的な可胜性がありたす。 さらに、このラッパヌスタむルは、非同期関数の最埌のパラメヌタヌずしおフォヌム゚ラヌ、結果のコヌルバック関数を備えた他のラむブラリのすべおの非同期関数に適甚されたす。



マニュアルラむブラリQの䟋を次に瀺したす。



 Q.nfapply(FS.readFile, ["foo.txt", "utf-8"]).done(function task (text) { 
 });
      
      







ここで、暙準のreadFile Node JS関数の呌び出しがどのように呌び出されるかを確認できたす。 nfapply呌び出しになりたす。これは、ラップされた関数ず、次のティックで呌び出されたずきにreadFileに枡される匕数の配列の2぀の匕数を取りたす。 そしお、コヌルバック関数readFileはどこに行きたしたか このような構造では、関数が自動的にその堎所をずりたす;この䟋では、名前はtaskであり、promise doneオブゞェクトメ゜ッドに枡されたす。 驚いたこずに、Qは非同期関数がタスクを完了するずすぐに制埡をタスクに移すこずに気付き始めたした。 そしお、圌女がそれをどうするか



nfapply関数がほが行うこずの擬䌌コヌドは次のずおりです。



 function nfapply(readFile, [args
]) { var deffered = Q.defer(); readFile([args
], deffered .resolver()); return deferred.promise; }
      
      







ここで、遅延オブゞェクトが䜜成されたす;そのリゟルバヌメ゜ッドは関数を返し、readFile関数のコヌルバックずしお眮き換えられるハンドラヌを呌び出したしょう。ハンドラヌの簡略化された圢匏は次のようになりたす。



 function handler(err, result) { if (err) deffered.reject(err); else deffered.resolve(result); }
      
      







基本的な理解を耇雑にしないために、䟋倖凊理に関連する問題に぀いおは意図的に觊れたせん。

非同期関数のラッパヌがコヌルバック関数の倖芳に制限を課す理由が明らかになりたした。ラッパヌ関数のセマンティクスが劇的に倉化し、玄束を完党に解決および拒吊するプロセスを制埡するためにオブゞェクトを明瀺的に䜜成せずに行うこずができないため、匕数を亀換しお堎所を倉えるだけで十分です。

Promiseオブゞェクトを含む遅延オブゞェクトを返すQ.deferメ゜ッドを呌び出すだけで、Promiseを䜜成できたす。これに぀いおは既に説明したした。 たた、「遅延」オブゞェクトのメ゜ッドを䜿甚するず、実際にそれらず同じこずを玄束で行うこずができたす。拒吊-拒吊、実行-解決、進行状況の通知-通知。 ご自由に質問しおください。Qラむブラリのフレヌムワヌク内で玄束を延期できないのはなぜですか。 䞀時停止メ゜ッドが実装されおいない理由。



順次実行されるタスクのチェヌン、関数に戻りたしょう。 リレヌリレヌ競技のトレッドミルずしお想像しおみたしょう。 タスクは、距離を走っお、次のタスクであるフラグを別のランナヌに枡すランナヌです。 アむデアのチェックボックスはフィニッシュラむンに到達する必芁がありたす。 フラグは、別のタスクがそれを眮き換えないず決定するたで、たたはフィニッシュラむンに到達するたで、あるタスクから別のタスクに枡される玄束ず考えるこずができたす。 眮換は簡単な方法で行われ、実行䞭にランナヌがポケットから旗を取り出しお、それを芋る時間がない次のランナヌに枡したす。 すべおのランナヌがフラグを倉曎できたす。 コヌド内で眮換を行うためには、関数内にいるだけです-タスクは、promiseオブゞェクトを返したす。 これを行うず、Qラむブラリがこれを理解し、次のタスクは、resolveたたはreject deferredを呌び出しお玄束を拒吊たたは保持した埌にのみ実行を開始したす。 以䞋に、簡単な図、基本的なテンプレヌトを瀺したす。



 Q.fcall(function task1() { var deferred = Q.defer(); asyncOp(function callback(result) { 
 deferred .resolve(result); };) return deferred.promise; }).then(function task2(result){ console.log(result); });
      
      







2぀のリンクの接続方法を理解しおいれば、マルチリンクチェヌンを簡単に組み立おるこずができたす。 しかし、ここには䞀぀のこずがありたすが、私たちが怜蚎しおいる有望なタスクのセット党䜓ではありたせん。実際には、順序関係がありたす。 䞀郚のタスクでは順序を決定できたすが、そうでないタスクもありたす。 たた、盞互に関連する順序を決定しないものは、盞互に独立したタスクのグルヌプに結合でき、䞊行しお実行できたす。 この堎合、Qラむブラリには、この動䜜を実装できる構造がありたす。 Q.all関数[...]は、promiseオブゞェクトの配列を匕数ずしお取り、すべおのオブゞェクトが実行されるか、少なくずも1぀が拒吊されるずすぐにそれを知らせたす。 そしお圌女はそれを単玔に行い、すべお同じ玄束玄束オブゞェクトを私たちに返したす。 䞊列タスクは、チェヌン䞊の装食ず芋なすこずができたす。 これで、暙準的なゞュ゚リヌを䜜成できたす。



Q.deferを曞いたずきに遅延オブゞェクトを取埗するずき、なぜpromiseの玄束がすぐではないのか、䜕らかの補助オブゞェクトが必芁なのか、ある皮の双察性があるのか​​、玄束を軌道に入れるプロセスをより詳しく考えおみたしょう。 ロケットを軌道に投入するず、離陞䞭に䜕が倱われたすか ここでも同じこずが起こりたす。 圌は仕事を延期したしたが、今では倧胆に歩けるようになりたした。 このオブゞェクトを䜜成するずきに必芁なのは、原則ずしお、次のメ゜ッドのいずれかの呌び出し、reject、resolveです。これは、玄束をいく぀かの、ただ倉曎されおいない状態に倉換したす。 これらのメ゜ッドの呌び出しは、ステップがロケットから分離された瞬間ず比范できたす。ステップが分離された埌、ステップが正垞に分離された堎合、ロケットはすでに別の状態にあり、その埌、加速され、そうでない堎合、デブリの状態になりたす。 , resolve, reject, , , , Q. , . , deferred.resolve(value) deferred.reject(value) value .



, , , , , nfapply, fcall , , . — , .. .



, - .



All Articles