サーチ…
Webブラウザのイベントループ
現代のJavaScript環境の大部分は、 イベントループに従って動作します 。これは、プログラムが新しいことが起こるのを絶えず待っていることを意味します。 ホスト環境はあなたのプログラムを呼び出し、イベントループで "turn"または "tick"または "task"を生成し、それが完了して実行されます。そのターンが終了すると、ホスト環境はこれが始まる前に、何か他のことが起こるのを待ちます。
これの簡単な例はブラウザにあります。次の例を考えてみましょう。
<!DOCTYPE html> <title>Event loop example</title> <script> console.log("this a script entry point"); document.body.onclick = () => { console.log("onclick"); }; setTimeout(() => { console.log("setTimeout callback log 1"); console.log("setTimeout callback log 2"); }, 100); </script>
この例では、ホスト環境はWebブラウザです。
- HTMLパーサーは、最初に
<script>
実行し<script>
。それは完了するまで実行されます。 -
setTimeout
の呼び出しは、ブラウザに、100ミリ秒後に、指定されたアクションを実行するタスクをエンキューする必要があることをブラウザに通知します。 - その間、イベントループは、何か他に何かがあるかどうかを継続的にチェックする責任があります。たとえば、Webページのレンダリングです。
- 100ミリ秒後に、イベントループが何らかの理由でビジー状態でない場合、
setTimeout
エンキューするタスクが表示され、関数を実行してこれら2つのステートメントを記録します。 - 誰かがボディをクリックするといつでも、ブラウザはイベントループにタスクをポストしてクリックハンドラ機能を実行します。イベントループは、何をすべきかを絶えずチェックしながら、これを見て、その機能を実行します。
この例では、イベントループによって呼び出されるJavaScriptコードへのエントリポイントのいくつかのタイプがどのようにあるかを見ることができます。
-
<script>
要素はすぐに呼び出されます -
setTimeout
タスクがイベントループにポストされ、1回実行されます。 - クリックハンドラタスクは、何回も投稿して毎回実行することができます
イベントループの各ターンは多くのことを担当します。それらの一部だけがこれらのJavaScriptタスクを呼び出すでしょう。詳細については、HTML仕様を参照してください。
最後の1つ:各イベントループタスクが「完了するまで実行する」と言ってどういう意味ですか?つまり、タスクとして実行するためにキューに入れられたコードブロックを中断することは一般的に不可能であり、別のコードブロックでインターリーブされたコードを実行することは決してできません。たとえば、完璧な時刻にクリックしたとしても、2つのsetTimeout callback log 1/2"
間に"onclick"
を記録する上記のコードを得ることはできませんでした。これはタスクの投稿の仕組みによるものですプリエンプティブではなく、協調的でキューベースです。
非同期操作とイベントループ
一般的なJavaScriptプログラミング環境における多くの面白い操作は非同期です。たとえば、ブラウザでは次のようなものが見られます。
window.setTimeout(() => { console.log("this happens later"); }, 100);
Node.jsには次のようなものがあります
fs.readFile("file.txt", (err, data) => { console.log("data"); });
これはイベントループとどのように適合しますか?
これがどのように機能するかは、これらのステートメントが実行されるときに、 ホスト環境 (つまり、ブラウザまたはNode.jsランタイム)が別のスレッドの中で何かを実行するように指示することです。ホスト環境が(それぞれ100ミリ秒を待っているかfile.txt
読み込んで)ホスト環境を終了すると、「前にこれらの引数で与えられたコールバックを呼び出す」というイベントループにタスクがポストされます。
イベントループは、Webページのレンダリング、ユーザー入力のリッスン、投稿されたタスクの継続的な探しなど、ビジー状態になります。これらのポストされたタスクがコールバックを呼び出すのを見ると、JavaScriptにコールバックします。これが非同期動作を得る方法です。