JavaScriptでのイベントループ、コールバック、プロミス、非同期/待機について理解する
著者はCOVID-19救済基金を選択し、 Write forDOnationsプログラムの一環として寄付を受け取りました。
序章
インターネットの初期には、WebサイトはHTMLページの静的データで構成されていました。 しかし、Webアプリケーションがよりインタラクティブで動的になった今、APIデータを取得するための外部ネットワーク要求を行うなどの集中的な操作を行うことがますます必要になっています。 JavaScriptでこれらの操作を処理するには、開発者は非同期プログラミング手法を使用する必要があります。
JavaScriptはシングルスレッドプログラミング言語であり、同期実行モデルが次々に操作を処理するため、一度に処理できるのは1つのステートメントのみです。 ただし、APIからのデータの要求などのアクションは、要求されるデータのサイズ、ネットワーク接続の速度、およびその他の要因によっては、不確定な時間がかかる場合があります。 API呼び出しが同期的に実行された場合、ブラウザは、その操作が完了するまで、スクロールやボタンのクリックなどのユーザー入力を処理できません。 これは、ブロッキングとして知られています。
ブロッキング動作を防ぐために、ブラウザ環境には、JavaScriptがアクセスできる非同期の多くのWeb APIがあります。つまり、それらは順番にではなく、他の操作と並行して実行できます。 これは、非同期操作の処理中にユーザーがブラウザーを通常どおり使用し続けることができるため便利です。
JavaScript開発者は、非同期Web APIを操作し、それらの操作の応答またはエラーを処理する方法を知っている必要があります。 この記事では、イベントループ、コールバックを介して非同期動作を処理する元の方法、更新された ECMAScript 2015 のpromiseの追加、およびasync/await
を使用する最新の方法について学習します。
注:この記事は、ブラウザー環境でのクライアント側のJavaScriptに焦点を当てています。 同じ概念がNode.js環境でも一般的に当てはまりますが、Node.jsはブラウザーの WebAPIではなく独自のC++APIを使用します。 Node.jsでの非同期プログラミングの詳細については、Node.jsで非同期コードを作成する方法を確認してください。
イベントループ
このセクションでは、JavaScriptがイベントループを使用して非同期コードを処理する方法について説明します。 まず、動作中のイベントループのデモンストレーションを実行し、次にイベントループの2つの要素であるスタックとキューについて説明します。
非同期WebAPIを使用しないJavaScriptコードは、同期的に1つずつ順番に実行されます。 これは、それぞれがconsoleに番号を出力する3つの関数を呼び出すこのサンプルコードによって示されます。
// Define three example functions function first() { console.log(1) } function second() { console.log(2) } function third() { console.log(3) }
このコードでは、console.log()
で数値を出力する3つの関数を定義します。
次に、関数への呼び出しを記述します。
// Execute the functions first() second() third()
出力は、関数が呼び出された順序(first()
、second()
、third()
)に基づきます。
Output1 2 3
非同期WebAPIを使用すると、ルールがより複雑になります。 これをテストできる組み込みAPIはsetTimeout
で、タイマーを設定し、指定された時間が経過するとアクションを実行します。 setTimeout
は非同期である必要があります。そうしないと、待機中にブラウザー全体がフリーズしたままになり、ユーザーエクスペリエンスが低下します。
setTimeout
をsecond
関数に追加して、非同期要求をシミュレートします。
// Define three example functions, but one of them contains asynchronous code function first() { console.log(1) } function second() { setTimeout(() => { console.log(2) }, 0) } function third() { console.log(3) }
setTimeout
は、2つの引数を取ります。非同期で実行される関数と、その関数を呼び出す前に待機する時間です。 このコードでは、console.log
を無名関数でラップし、setTimeout
に渡してから、0
ミリ秒後に実行するように関数を設定しました。
前に行ったように、関数を呼び出します。
// Execute the functions first() second() third()
setTimeout
を0
に設定すると、これら3つの関数を実行しても、番号が順番に出力されることが予想されます。 ただし、非同期であるため、タイムアウトのある関数は最後に出力されます。
Output1 3 2
タイムアウトを0秒に設定しても5分に設定しても、違いはありません。非同期コードによって呼び出されるconsole.log
は、同期トップレベル関数の後に実行されます。 これは、JavaScriptホスト環境(この場合はブラウザー)がイベントループと呼ばれる概念を使用して、同時実行または並列イベントを処理するために発生します。 JavaScriptは一度に1つのステートメントしか実行できないため、どの特定のステートメントをいつ実行するかをイベントループに通知する必要があります。 イベントループは、スタックとキューの概念でこれを処理します。
スタック
スタック、または呼び出しスタックは、現在実行されている関数の状態を保持します。 スタックの概念に慣れていない場合は、「後入れ先出し」(LIFO)プロパティを持つ配列として想像できます。つまり、最後からアイテムを追加または削除することしかできません。スタック。 JavaScriptは、スタック内の現在の frame (または特定の環境での関数呼び出し)を実行し、それを削除して次のフレームに移動します。
同期コードのみを含む例の場合、ブラウザは次の順序で実行を処理します。
first()
をスタックに追加し、first()
を実行して1
をコンソールに記録し、スタックからfirst()
を削除します。second()
をスタックに追加し、second()
を実行して2
をコンソールに記録し、スタックからsecond()
を削除します。third()
をスタックに追加し、third()
を実行して3
をコンソールに記録し、スタックからthird()
を削除します。
setTimout
の2番目の例は、次のようになります。
first()
をスタックに追加し、first()
を実行して1
をコンソールに記録し、スタックからfirst()
を削除します。second()
をスタックに追加し、second()
を実行します。 スタックにsetTimeout()を追加し、タイマーを開始して無名関数をキューに追加するsetTimeout()Web APIを実行し、スタックからsetTimeout()を削除します。- スタックから
second()
を削除します。 third()
をスタックに追加し、third()
を実行して3
をコンソールに記録し、スタックからthird()
を削除します。- イベントループは、保留中のメッセージがないかキューをチェックし、
setTimeout()
から無名関数を見つけ、2
をコンソールに記録するスタックに関数を追加し、スタックから削除します。
非同期WebAPIであるsetTimeout
を使用して、このチュートリアルで次に説明するキューの概念を紹介します。
列
キューは、メッセージキューまたはタスクキューとも呼ばれ、機能の待機領域です。 コールスタックが空の場合は常に、イベントループは、最も古いメッセージから開始して、待機中のメッセージがないかキューをチェックします。 見つかったら、それをスタックに追加し、メッセージ内の関数を実行します。
setTimeout
の例では、タイマーが0
秒に設定されているため、匿名関数は残りのトップレベル実行の直後に実行されます。 タイマーは、コードが正確に0
秒または指定された時間で実行されることを意味するのではなく、その時間内に匿名関数をキューに追加することを覚えておくことが重要です。 このキューシステムが存在するのは、タイマーの終了時にタイマーが匿名関数をスタックに直接追加すると、現在実行中の関数が中断され、意図しない予期しない影響が生じる可能性があるためです。
注:promiseを処理するジョブキューまたはマイクロタスクキューと呼ばれる別のキューもあります。 promiseのようなマイクロタスクは、setTimeout
のようなマクロタスクよりも高い優先度で処理されます。
これで、イベントループがスタックとキューを使用してコードの実行順序を処理する方法がわかりました。 次のタスクは、コードの実行順序を制御する方法を理解することです。 これを行うには、最初に、非同期コードがイベントループによって正しく処理されるようにする元の方法であるコールバック関数について学習します。
コールバック関数
setTimeout
の例では、タイムアウトのある関数は、メインのトップレベルの実行コンテキストのすべての後に実行されました。 ただし、third
関数などの関数のいずれかがタイムアウト後に実行されるようにする場合は、非同期コーディング方式を使用する必要があります。 ここでのタイムアウトは、データを含む非同期API呼び出しを表すことができます。 API呼び出しからのデータを処理したいが、データが最初に返されることを確認する必要があります。
この問題に対処するための元の解決策は、コールバック関数を使用することです。 コールバック関数には特別な構文はありません。 これらは、引数として別の関数に渡された関数にすぎません。 別の関数を引数とする関数を高階関数と呼びます。 この定義によれば、引数として渡された場合、任意の関数がコールバック関数になる可能性があります。 コールバックは本質的に非同期ではありませんが、非同期の目的で使用できます。
高階関数とコールバックの構文コードの例を次に示します。
// A function function fn() { console.log('Just a function') } // A function that takes another function as an argument function higherOrderFunction(callback) { // When you call a function that is passed as an argument, it is referred to as a callback callback() } // Passing a function higherOrderFunction(fn)
このコードでは、関数fn
を定義し、関数callback
を引数として取る関数higherOrderFunction
を定義し、fn
をコールバックとして渡します。 higherOrderFunction
。
このコードを実行すると、次のようになります。
OutputJust a function
first
、second
、およびthird
機能にsetTimeout
を使用して戻りましょう。 これはあなたがこれまでに持っているものです:
function first() { console.log(1) } function second() { setTimeout(() => { console.log(2) }, 0) } function third() { console.log(3) }
タスクは、third
関数を取得して、second
関数の非同期アクションが完了するまで常に実行を遅らせることです。 これがコールバックの出番です。 実行のトップレベルでfirst
、second
、およびthird
を実行する代わりに、third
関数を引数としてsecond
。 second
関数は、非同期アクションが完了した後にコールバックを実行します。
コールバックが適用された3つの関数は次のとおりです。
// Define three functions function first() { console.log(1) } function second(callback) { setTimeout(() => { console.log(2) // Execute the callback function callback() }, 0) } function third() { console.log(3) }
ここで、first
とsecond
を実行し、third
を引数としてsecond
に渡します。
first() second(third)
このコードブロックを実行すると、次の出力が表示されます。
Output1 2 3
最初に1
が印刷され、タイマーが完了すると(この場合、0秒ですが、任意の量に変更できます)、2
、次に3
が印刷されます。 関数をコールバックとして渡すことにより、非同期Web API(setTimeout
)が完了するまで関数の実行を正常に遅らせることができます。
ここで重要なポイントは、コールバック関数が非同期ではないことです。setTimeout
は、非同期タスクの処理を担当する非同期WebAPIです。 コールバックを使用すると、非同期タスクが完了したときに通知を受け、タスクの成功または失敗を処理できます。
コールバックを使用して非同期タスクを処理する方法を学習したので、次のセクションでは、あまりにも多くのコールバックをネストして「運命のピラミッド」を作成する問題について説明します。
ネストされたコールバックと運命のピラミッド
コールバック関数は、別の関数が完了してデータを返すまで、関数の実行を遅らせるための効果的な方法です。 ただし、コールバックはネストされているため、相互に依存する連続した非同期リクエストが多数ある場合、コードが乱雑になる可能性があります。 これは、JavaScript開発者にとって初期の大きなフラストレーションであり、その結果、ネストされたコールバックを含むコードは、「運命のピラミッド」または「コールバック地獄」と呼ばれることがよくあります。
ネストされたコールバックのデモンストレーションは次のとおりです。
function pyramidOfDoom() { setTimeout(() => { console.log(1) setTimeout(() => { console.log(2) setTimeout(() => { console.log(3) }, 500) }, 2000) }, 1000) }
このコードでは、新しいsetTimeout
はそれぞれ高階関数内にネストされ、より深いコールバックのピラミッド形状を作成します。 このコードを実行すると、次のようになります。
Output1 2 3
実際には、実際の非同期コードでは、これははるかに複雑になる可能性があります。 ほとんどの場合、非同期コードでエラー処理を実行してから、各応答から次の要求にデータを渡す必要があります。 コールバックを使用してこれを行うと、コードの読み取りと保守が困難になります。
これは、より現実的な「運命のピラミッド」の実行可能な例です。
// Example asynchronous function function asynchronousRequest(args, callback) { // Throw an error if no arguments are passed if (!args) { return callback(new Error('Whoa! Something went wrong.')) } else { return setTimeout( // Just adding in a random number so it seems like the contrived asynchronous function // returned different data () => callback(null, {body: args + ' ' + Math.floor(Math.random() * 10)}), 500, ) } } // Nested asynchronous requests function callbackHell() { asynchronousRequest('First', function first(error, response) { if (error) { console.log(error) return } console.log(response.body) asynchronousRequest('Second', function second(error, response) { if (error) { console.log(error) return } console.log(response.body) asynchronousRequest(null, function third(error, response) { if (error) { console.log(error) return } console.log(response.body) }) }) }) } // Execute callbackHell()
このコードでは、すべての関数が可能なresponse
と可能なerror
を考慮に入れる必要があり、関数callbackHell
が視覚的に混乱します。
このコードを実行すると、次のようになります。
Output First 9 Second 3 Error: Whoa! Something went wrong. at asynchronousRequest (<anonymous>:4:21) at second (<anonymous>:29:7) at <anonymous>:9:13
非同期コードを処理するこの方法に従うのは困難です。 その結果、promisesの概念がES6に導入されました。 これが次のセクションの焦点です。
約束
promise は、非同期機能の完了を表します。 将来的に値を返す可能性のあるオブジェクトです。 コールバック関数と同じ基本的な目標を達成しますが、多くの追加機能とより読みやすい構文を備えています。 JavaScript開発者は、プロミスを作成するよりも多くの時間を費やす可能性があります。これは、通常、開発者が消費するプロミスを返す非同期WebAPIであるためです。 このチュートリアルでは、両方を行う方法を説明します。
約束を作成する
new Promise
構文を使用してpromiseを初期化でき、関数を使用して初期化する必要があります。 promiseに渡される関数には、resolve
およびreject
パラメーターがあります。 resolve
関数とreject
関数は、それぞれ操作の成功と失敗を処理します。
約束を宣言するには、次の行を記述します。
// Initialize a promise const promise = new Promise((resolve, reject) => {})
この状態で初期化されたpromiseをWebブラウザーのコンソールで調べると、pending
ステータスとundefined
値があることがわかります。
Output__proto__: Promise [[PromiseStatus]]: "pending" [[PromiseValue]]: undefined
これまでのところ、約束のために何も設定されていないので、それは永遠にpending
状態でそこに座るでしょう。 約束をテストするために最初にできることは、値でそれを解決することによって約束を果たすことです。
const promise = new Promise((resolve, reject) => { resolve('We did it!') })
これで、Promiseを調べると、ステータスがfulfilled
であり、value
がresolve
に渡した値に設定されていることがわかります。
Output__proto__: Promise [[PromiseStatus]]: "fulfilled" [[PromiseValue]]: "We did it!"
このセクションの冒頭で述べたように、promiseは値を返す可能性のあるオブジェクトです。 正常に実行されると、value
はundefined
からデータが入力されます。
約束には、保留中、履行済み、および拒否の3つの状態があります。
- 保留中-解決または拒否される前の初期状態
- Fulfilled -正常な操作、promiseは解決されました
- 却下-操作に失敗しました。Promiseは却下されました
履行または拒否された後、約束は解決されます。
これで、Promiseがどのように作成されるかがわかったので、開発者がこれらのPromiseをどのように使用するかを見てみましょう。
約束を消費する
前のセクションの約束は値で満たされましたが、値にアクセスできるようにする必要もあります。 Promiseにはthen
というメソッドがあり、コード内でPromiseがresolve
に達した後に実行されます。 then
は、promiseの値をパラメーターとして返します。
これは、サンプルpromiseのvalue
を返してログに記録する方法です。
promise.then((response) => { console.log(response) })
あなたが作成した約束には、We did it!
のPromiseValue
がありました。 この値は、response
として匿名関数に渡される値です。
OutputWe did it!
これまでのところ、作成した例には非同期Web APIは含まれていませんでした。これは、ネイティブJavaScript Promiseを作成、解決、および使用する方法のみを説明したものです。 setTimeout
を使用して、非同期リクエストをテストできます。
次のコードは、非同期リクエストから返されるデータをpromiseとしてシミュレートします。
const promise = new Promise((resolve, reject) => { setTimeout(() => resolve('Resolving an asynchronous request!'), 2000) }) // Log the result promise.then((response) => { console.log(response) })
then
構文を使用すると、2000
ミリ秒後にsetTimeout
操作が完了した場合にのみ、response
がログに記録されます。 これはすべて、コールバックをネストせずに実行されます。
2秒後、promise値が解決され、then
にログインします。
OutputResolving an asynchronous request!
Promiseをチェーン化して、データを複数の非同期操作に渡すこともできます。 then
に値が返された場合、前のthen
の戻り値を満たす別のthen
を追加できます。
// Chain a promise promise .then((firstResponse) => { // Return a new value for the next then return firstResponse + ' And chaining!' }) .then((secondResponse) => { console.log(secondResponse) })
2番目のthen
で満たされた応答は、戻り値をログに記録します。
OutputResolving an asynchronous request! And chaining!
then
は連鎖できるため、promiseの消費は、ネストする必要がないため、コールバックよりも同期的に見えるようになります。 これにより、より読みやすいコードが可能になり、保守と検証が容易になります。
エラー処理
これまでのところ、resolve
が成功した場合にのみ、Promiseを処理しました。これにより、Promiseはfulfilled
状態になります。 ただし、非同期リクエストでは、APIがダウンしている場合や、不正な形式または不正なリクエストが送信された場合に、エラーを処理する必要があることがよくあります。 約束は両方の場合を処理できるはずです。 このセクションでは、promiseの作成と使用の成功とエラーの両方のケースをテストする関数を作成します。
このgetUsers
関数は、promiseにフラグを渡し、promiseを返します。
function getUsers(onSuccess) { return new Promise((resolve, reject) => { setTimeout(() => { // Handle resolve and reject in the asynchronous API }, 1000) }) }
onSuccess
がtrue
の場合、タイムアウトが一部のデータで満たされるようにコードを設定します。 false
の場合、関数は次のエラーで拒否します。
function getUsers(onSuccess) { return new Promise((resolve, reject) => { setTimeout(() => { // Handle resolve and reject in the asynchronous API if (onSuccess) { resolve([ {id: 1, name: 'Jerry'}, {id: 2, name: 'Elaine'}, {id: 3, name: 'George'}, ]) } else { reject('Failed to fetch data!') } }, 1000) }) }
正常な結果を得るには、サンプルユーザーデータを表すJavaScriptオブジェクトを返します。
エラーを処理するには、catch
インスタンスメソッドを使用します。 これにより、error
をパラメーターとして使用した失敗コールバックが提供されます。
onSuccess
をfalse
に設定して、getUser
コマンドを実行します。成功した場合は、then
メソッドを使用し、エラーの場合はcatch
メソッドを使用します。 :
// Run the getUsers function with the false flag to trigger an error getUsers(false) .then((response) => { console.log(response) }) .catch((error) => { console.error(error) })
エラーがトリガーされたため、then
はスキップされ、catch
がエラーを処理します。
OutputFailed to fetch data!
フラグとresolve
を切り替えると、catch
は無視され、代わりにデータが返されます。
// Run the getUsers function with the true flag to resolve successfully getUsers(true) .then((response) => { console.log(response) }) .catch((error) => { console.error(error) })
これにより、ユーザーデータが生成されます。
Output(3) [{…}, {…}, {…}] 0: {id: 1, name: "Jerry"} 1: {id: 2, name: "Elaine"} 3: {id: 3, name: "George"}
参考までに、Promise
オブジェクトのハンドラーメソッドの表を次に示します。
方法 | 説明 |
---|---|
then()
|
resolve を処理します。 promiseを返し、onFulfilled 関数を非同期で呼び出します
|
catch()
|
reject を処理します。 promiseを返し、onRejected 関数を非同期で呼び出します
|
finally()
|
約束が決まったときに呼び出されます。 promiseを返し、onFinally 関数を非同期で呼び出します
|
これまで非同期環境で作業したことがない新しい開発者と経験豊富なプログラマーの両方にとって、約束は混乱を招く可能性があります。 ただし、前述のように、プロミスを作成するよりも消費する方がはるかに一般的です。 通常、ブラウザのWeb APIまたはサードパーティのライブラリが約束を提供し、それを使用するだけで済みます。
最後のpromiseセクションでは、このチュートリアルで、promiseを返すWeb APIの一般的なユースケースを引用します: FetchAPI。
PromisesでのFetchAPIの使用
promiseを返す最も便利で頻繁に使用されるWebAPIの1つは、Fetch APIです。これにより、ネットワークを介して非同期リソース要求を行うことができます。 fetch
は2つの部分からなるプロセスであるため、then
をチェーンする必要があります。 この例は、GitHub APIをヒットしてユーザーのデータをフェッチすると同時に、潜在的なエラーを処理する方法を示しています。
// Fetch a user from the GitHub API fetch('https://api.github.com/users/octocat') .then((response) => { return response.json() }) .then((data) => { console.log(data) }) .catch((error) => { console.error(error) })
fetch
リクエストはhttps://api.github.com/users/octocat
URLに送信され、非同期で応答を待ちます。 最初のthen
は、応答を JSONデータとしてフォーマットする無名関数に応答を渡し、次に、データをコンソールに記録する2番目のthen
にJSONを渡します。 catch
ステートメントは、エラーをコンソールに記録します。
このコードを実行すると、次のようになります。
Outputlogin: "octocat", id: 583231, avatar_url: "https://avatars3.githubusercontent.com/u/583231?v=4" blog: "https://github.blog" company: "@github" followers: 3203 ...
これは、https://api.github.com/users/octocat
から要求されたデータであり、JSON形式でレンダリングされます。
チュートリアルのこのセクションでは、promiseに非同期コードを処理するための多くの改善が組み込まれていることを示しました。 ただし、then
を使用して非同期アクションを処理するのは、コールバックのピラミッドよりも簡単ですが、一部の開発者は、非同期コードを記述する同期形式を好む場合があります。 このニーズに対応するために、 ECMAScript 2016(ES7)は、async
関数とawait
キーワードを導入して、promiseの操作を容易にしました。
async/await
を使用した非同期関数
非同期関数を使用すると、同期しているように見える方法で非同期コードを処理できます。 async
関数は、内部でpromiseを使用しますが、より伝統的なJavaScript構文を使用します。 このセクションでは、この構文の例を試してみます。
関数の前にasync
キーワードを追加すると、async
関数を作成できます。
// Create an async function async function getUser() { return {} }
この関数はまだ非同期を処理していませんが、従来の関数とは動作が異なります。 関数を実行すると、戻り値の代わりにPromiseStatus
とPromiseValue
のpromiseが返されることがわかります。
getUser
関数への呼び出しをログに記録して、これを試してください。
console.log(getUser())
これにより、次のようになります。
Output__proto__: Promise [[PromiseStatus]]: "fulfilled" [[PromiseValue]]: Object
これは、promiseを処理するのと同じ方法で、async
関数をthen
で処理できることを意味します。 次のコードでこれを試してください。
getUser().then((response) => console.log(response))
このgetUser
の呼び出しは、戻り値を匿名関数に渡し、匿名関数は値をコンソールに記録します。
このプログラムを実行すると、次のメッセージが表示されます。
Output{}
async
関数は、await
演算子を使用してその中で呼び出されたpromiseを処理できます。 await
は、async
関数内で使用でき、promiseが解決するまで待機してから、指定されたコードを実行します。
この知識があれば、次のようにasync
/ await
を使用して、前のセクションのフェッチ要求を書き換えることができます。
// Handle fetch with async/await async function getUser() { const response = await fetch('https://api.github.com/users/octocat') const data = await response.json() console.log(data) } // Execute async function getUser()
ここでのawait
演算子は、リクエストがデータを入力する前にdata
がログに記録されないようにします。
これで、then
を使用しなくても、data
をgetUser
関数内で処理できるようになりました。 これは、ロギングdata
の出力です。
Outputlogin: "octocat", id: 583231, avatar_url: "https://avatars3.githubusercontent.com/u/583231?v=4" blog: "https://github.blog" company: "@github" followers: 3203 ...
注:多くの環境では、await
を使用するにはasync
が必要ですが、一部の新しいバージョンのブラウザーとノードでは、トップレベルのawait
を使用できます。これにより、await
をラップする非同期関数の作成をバイパスできます。
最後に、非同期関数内で実行されたpromiseを処理しているため、関数内でエラーを処理することもできます。 catch
メソッドをthen
で使用する代わりに、 try /catchパターンを使用して例外を処理します。
次の強調表示されたコードを追加します。
// Handling success and errors with async/await async function getUser() { try { // Handle success in try const response = await fetch('https://api.github.com/users/octocat') const data = await response.json() console.log(data) } catch (error) { // Handle error in catch console.error(error) } }
エラーを受信した場合、プログラムはcatch
ブロックにスキップし、そのエラーをコンソールに記録します。
最新の非同期JavaScriptコードは、ほとんどの場合async
/ await
構文で処理されますが、特にPromiseは処理できない追加機能に対応しているため、Promiseがどのように機能するかについて実用的な知識を持っていることが重要です。 async
/ await
を使用します。たとえば、promiseを Promise.all()と組み合わせます。
ノート: async
/await
can be reproduced by using ジェネレーターとプロミスの組み合わせ to add more flexibility to your code. To learn more, check out our JavaScriptのジェネレーターを理解する tutorial.
結論
Web APIはデータを非同期で提供することが多いため、非同期アクションの結果を処理する方法を学ぶことは、JavaScript開発者であるための重要な部分です。 この記事では、ホスト環境がイベントループを使用して、スタックおよびキューでコードの実行順序を処理する方法を学習しました。 また、コールバック、promise、およびasync
/ await
構文を使用して、非同期イベントの成功または失敗を処理する3つの方法の例を試しました。 最後に、FetchWebAPIを使用して非同期アクションを処理しました。
ブラウザが並列イベントを処理する方法の詳細については、MozillaDeveloperNetworkの同時実行モデルとイベントループを参照してください。 JavaScriptについて詳しく知りたい場合は、JavaScriptでコーディングする方法シリーズに戻ってください。