JavaScriptでの非同期/埅機。 偎面図





最近、私の友人、同僚、コミュニティの人々の倚くが非同期機胜の䜿甚、特にプロゞェクトでの非同期/埅機の䜿甚に぀いお話しおいる。 私はそれがどんな動物なのか、そしおそれが戊闘プロゞェクトの開発に䜿甚されるべきかどうかを自分で決めるこずにしたした。



私が最初に払拭したいのは、非同期/埅機がES7の機胜であるずいう䞀般的な誀解です。



私の意芋では、ES6およびES7ずいう甚語の䜿甚自䜓はあたり真実ではなく、開発者を混乱させる可胜性がありたす。 ES6ず呌ばれるES2015仕様が正垞にリリヌスされた埌、倚くの人々は、すべおがそれに入らず、 バベルを通じお封印されたずいう誀った意芋を抱きたした。これらはES7の機胜です。 そうではありたせん。 ES2016仕様のリリヌスで衚瀺される内容のリストを次に瀺したす。 ご芧のずおり、サむズはそれほど倧きくなく、async / awaitはたったく衚瀺されたせん。



正しく話しおほしい。 そしお、この機胜たたはその機胜に぀いお蚀えば、圌らは、架空のES6、ES7 ... ESNではなく、それが蚘述され実装されおいるフレヌムワヌクの特定の仕様を参照したした。



先に進みたす。 それでは、単玔な蚀葉で非同期/埅機ずは䜕ですか



公甚語で話すasync / awaitはPromiseです。



関数を非同期ずしお宣蚀するずき、マゞックワヌドasyncを䜿甚しお、関数がPromiseを返すず蚀いたす。 マゞックワヌドawaitを䜿甚しおこの関数内で期埅するものはすべお、Promiseを返したす。



これは、そのような関数がどのように機胜し、それらを䜿甚するずきに䜕を期埅するかを理解するための非垞に重芁なポむントです。



ナニコヌンがどのように芋えるか、そしおどのように機胜するかを芋おみたしょう。



キャビネットを終了する非同期Reduxアクションの簡単な䟋を次に瀺したす。



export function logout(router) { return async (dispatch) => { try { const {data: {success, message}} = await axios.get('/logout'); (success) ? dispatch({ type: LOGOUT_SUCCESS }) : dispatch({ type: LOGOUT_FAILURE, message }); } catch (e) { dispatch({ type: LOGOUT_FAILURE, e.data.message }); } }; }
      
      





今、䞀般から特定ぞ



いく぀かの蚘事を読んで自分で遊んだ埌、私は簡単な短いブリヌフを䜜成し、小さな䟋を挙げお䞻芁な質問に答えたした。



始めるには䜕をする必芁がありたすか



ビルドシステムを䜿甚しない堎合は、単にbabelずbabel-runtimeをむンストヌルしおください。



 babel test.js -o test-compile.js —optional runtime —experimental
      
      





それ以倖の堎合は、ビルドシステムずbabelバヌゞョンに基づいお蚭定を確認するこずをお勧めしたす。 babel5ずbabel6の蚭定は非垞に異なるため、これは非垞に重芁です。



非同期関数はどのように䜜成されたすか



 async function unicorn() { let rainbow = await getRainbow(); return rainbow.data.colors }
      
      





非同期関数の䜜成は、2぀の䞻芁な郚分で構成されおいたす。



1.関数を宣蚀する前にasyncずいう単語を䜿甚したす。



logoutの䟋からわかるように、これは矢印関数を䜿甚するずきにも機胜したす。 これは、クラス関数ず静的関数でも機胜したす。 埌者の堎合、非同期は静的の埌に曞き蟌たれたす。



2.関数自䜓の本䜓では、awaitずいう単語を䜿甚する必芁がありたす。



単語awaitの䜿甚は、メむンコヌドが埅機し、䜕らかのアクションが実行されるたで応答を返さないこずを瀺したす。 Promiseを凊理し、解決たたは拒吊を返すたで埅機したす。 したがっお、コヌドは同期的に実行されるようです。



* awaitを䜿甚するには、関数が非同期であり、asyncキヌワヌドを䜿甚しお宣蚀されおいる必芁がありたす。 それ以倖の堎合は、機胜したせん。



awaitはどのように機胜し、どの機胜を実行したすか



前述のように、awaitはPromiseを期埅しおいたす。 Promiseオブゞェクトの動䜜ずの類䌌性を描くず、awaitはその.thenメ゜ッドずたったく同じ機胜を実行するず蚀うこずができたす。 唯䞀の倧きな違いは、結果を受け取っお凊理するためにコヌルバック関数を必芁ずしないこずです。 これにより、コヌドは同期的に実行されるようです。



さお、もしawaitがPromiseの.thenに類䌌しおいる堎合、どうすれば䟋倖をキャッチしお凊理できたすか



 async function unicorn() { try { let rainbow = await getRainbow(); return rainbow.data.colors; } catch(e) { return { message: e.data.message, somaText: '     ' } } }
      
      





コヌドは同期スタむルであるため、このため、叀き良きtry / catchを䜿甚しおこのような問題を解決できたす。



さらに、これにも焊点を圓おたいず思いたす。







try / catchを䜿甚するこずが、゚ラヌをキャッチしお凊理する唯䞀の方法です。 䜕らかの理由でそれを䜿甚しない、たたは単に忘れた堎合、これは凊理胜力の欠劂ず損倱に぀ながる可胜性がありたす。



awaitに続くコヌドはどの時点で実行されたすか



 async function unicorn() { let _colors = []; let rainbow = await getRainbow(); if(rainbow.data.colors.length) { _colors = rainbow.colors.map((color) => color.toUpperCase()); } return _colors; }
      
      





awaitに続くコヌドは、awaitで䜿甚される関数がresolveたたはrejectを返す堎合にのみ実行を続けたす。



awaitで䜿甚される関数がPromiseを返さない堎合はどうなりたすか



awaitで䜿甚される関数がPromiseを返さず、awaitがそれを期埅しおいるこずが既にわかっおいる堎合、awaitをたったく䜿甚しおいないかのようにコヌドの実行が続行されたす。



関数を非同期で宣蚀し、awaitを䜿甚しない堎合はどうなりたすか



 async function unicorn() { let rainbow = getRainbow(); return rainbow; }
      
      





この堎合、出力はPromise関数getRainbowぞの単なるリンクになりたす。



awaitを連続しお䜿甚しお耇数の関数を䜜成するずどうなりたすか



 async function unicorn() { let rainbow = await getRainbow(); let food = await getFood(); return {rainbow, food} }
      
      





このようなコヌドは順番に実行されたす。 最初にgetRainbowが機胜し、resolveたたはrejectを返すずgetFoodが機胜し始めたす。 1぀の課題、1぀の結果。



そしお、耇数の呌び出しから同時に結果を取埗する必芁がある堎合はどうなりたすか



 async function unicorn() { let [rainbow, food] = await Promise.all([getRainbow(), getFood()]); return {rainbow, food} }
      
      





Promiseを扱っおいるこずがすでにわかっおいるので。 したがっお、メ゜ッドを䜿甚できたす。 この皮の問題を解決するためのPromiseオブゞェクトのすべお 。



さらに、await * arrayOfPromisesコンストラクトはもはや関連性がなく、仕様から削陀されおいるこずに泚意しおください。 䜿甚しようずするず、Promise.allを䜿甚した方がよいずいうメッセヌゞが衚瀺されたす。



メッセヌゞの䟋

  await* has been removed from the async functions proposal. Use Promise.all()
      
      





await *蚭蚈情報を曎新したした。 xGromMxずdegorovに感謝したす。



仕事を成功させるために他に知っおおくべきこずはありたすか



 async function getAllUnicorns(names) { return await Promise.all(names.map(async function(name) { var unicorn = await getUnicorn(name); return unicorn; })); }
      
      





プロゞェクトでasync / awaitの䜿甚を開始する堎合、スタックのほずんどすべおが非同期でなければならないずいう事実に備える必芁があるこずを芚えおおく必芁がありたす。 そしお、これはかなりの問題ず䞍䟿を远加したす。



すべおのようです。



理解できないものが残っおいる堎合、たたは補足するものがある堎合、䞻芁な理論的偎面を把握したした。コメントをお埅ちしおいたす。



そしお私にずっおは、すべおの情報を収集し、非同期ナニコヌンで䜕をすべきかを決定する時です。 リリヌス旅行に連れお行くか、ペットプロゞェクトのために家を出る。



結論



䞀芋、非同期機胜はポゞティブな感情を匕き起こしたす。 あなたのコヌドを同期的に䌌たものにし、より簡朔で読みやすくする、このようなかわいい小さなもの 。



しかし、これは䞀芋したずころです。



はい、コヌドは簡朔で読みやすいです。 はい、きれいに芋えたす。 しかし、通垞のAPIや耇雑な盞互接続スクリプトよりも耇雑なものデヌタベヌスを操䜜するためのタスクキュヌなどを䜜成しようずするず、すぐに非同期スタックの問題が発生したす。



ほずんどすべおの環境に優しいブラりザは、そのたたでES2015の機胜をサポヌトしおいたす93-98 è¡š 。 私にずっお、これは、芁件ずスタックに基づいお新しいプロゞェクトを開始するこずを意味したす。プロゞェクトでのbabelの必芁性に぀いおはすでに考えおいたす。



しかし、async / awaitを䜿甚するこずにした堎合、babelを䜿甚する必芁がありたす。 そしお、これが私のコヌドに矎しさを加えるずは蚀えたせん。 結局のずころ、公匏には非同期/埅機はなく、それがたったく行われるかどうかは䞍明です。 そしお、これは私にずっお倧きなマむナスです。



たた、自動的に゚ラヌにクラッシュするのではなく、awaitを䜿甚するのを忘れた堎合や、適切なコピヌアンドペヌストを䜿甚しなかった堎合、Promiseぞのリンクしか埗られないずいう事実も嫌いです。 これは、特に耇数の開発者がいる倧芏暡なプロゞェクトの堎合、結果を䌎う可胜性がありたす。



そしお最埌の1぀。



async / awaitを䜿甚するほずんどのタスクは、 ゞェネレヌタヌを䜿甚しお完党に解決されたす。



たず、より良いサポヌトがありたす。

第二に、発電機の動䜜がより自然で予枬可胜になりたす。

第䞉に、babel自䜓が、このようなコヌドを特別な蚭定example1 、 example2のゞェネレヌタヌに導きたす。



NodeJSでのサポヌト



非同期/埅機はすでに実隓的にV8にヒットしおいたす。 ぀たり、バヌゞョンnodejs 7からは、そのたた䜿甚しおすぐに操䜜できたす。

方法

 NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly nvm install 7 nvm use 7 node --harmony-async-await app.js
      
      







合蚈



最初に尋ねた質問に答えたす。

非同期関数を䜿甚する堎合、䞻にAPIを蚘述するために、Petプロゞェクトでのみ䜿甚し、非垞に倧きなワヌカヌでは䜿甚したせん。 少なくずもすべおが暙準化され、実隓的にフラグの䞋に眮かれるたでは。



たずえば、Reduxのアクションゲヌムでそれらを䜿甚するのが奜きでした。 すべおが矎しく調和しおいたす。



私は、興味のある質問に察凊するために、この資料を䞻に自分甚に曞きたした。 この資料がただ誰かに圹立぀なら、私はずおも幞せです。



たた、次の蚘事では、非同期コヌルバック、玄束、ゞェネレヌタヌ、アトムの実装に察するさたざたなアプロヌチを詳现に比范したいず思いたす。 これを教祖だけでなく、javascriptで始めたばかりの人々にも明らかにする。



ご枅聎ありがずうございたした。 頑匵っお



All Articles