質問: javascriptの非同期処理について勉強しています。 いくつかサイトを読み、自分なりに次のように理解しました。 jsはブラウザのUIスレッド(メインスレッド)で動いている。メインスレッドではjs以外にも画面の描画(ボタンのホバー処理)等が実行されている。まず、jsが読み込まれた時点で同期的に書かれた関数実行がjsに書かれた順番で実行待ちqueueに入る。メインスレッドはそのqueueを前から読んで実行する。 非同期処理では、例えばsetTimeout(callback, time)の場合、queueからsetTimeoutが呼ばれた時点でtime秒待つという処理をブラウザのタイマースレッドに投げ、自身は終了する。メインスレッドは次のqueueを読み他の関数を実行していく。タイマースレッドで指定の秒数が経過した時、メインスレッドに通知し、メインスレッドのqueueにcallbackを追加する。queがどんどん処理され、callbackに到達したので実行される。 まずこの理解が正しいでしょうか? この記事で、次のような記述がありました。 > > 「ある関数が呼び出されたとき、戻り値として本来渡したい結果を返すのではなく、一度関数としては終了し(=呼び出し元に戻る)、後で『本来渡したかった値』を返せる状態になったときに、呼び出し元にその値を通知する」という仕組みが非同期処理である。 > > 例えばサーバーと通信を行った際に、リクエストが返ってくるまでに数秒以上もかかると困る。 > > > ここで例としてあげられているサーバーとの通信で、「サーバーからデータが返ってきたか」を監視するのは誰が行っているのでしょうか?その処理は必ずどこかのスレッドで実行されているはずです。OSのtcp/ipを管理しているスレッドに、データ到着したときに通知してくれる仕組みがあって、そちらにデータの監視を任せている、と考えればよいのでしょうか? 「データが返ってくるのを待つ」という処理がsetTimeoutでブラウザのタイマースレッドが行っていたことと同じとみなせる、と理解しましたが正しいでしょうか? ![画像の説明をここに入力](https://i.stack.imgur.com/BaLya.png) そう考えたとしても次の疑問があります。 同じ記事で、fsが非同期処理として紹介されていますが、先程の例とは違い、こちらではファイルからデータを読み出すのはjs自身ではないでしょうか? 上の例では時間の掛かる処理であるwaitを他のスレッドが行ってくれていたためにメインスレッドは他の処理を行えていましたが、今回の例ではファイルを読み出す処理そのものがjs上で行われるため、重いデータを読み出す際に同期的にも非同期的にもメインスレッドで実行される以上メインスレッドを一定時間使ってしまうため、特に効率的ではないように思えます。 私のfsへの理解が間違っているのでしょうか? ご回答よろしくおねがいします。
回答: > > まずこの理解が正しいでしょうか? > > > と理解しましたが正しいでしょうか? > > > だいたいその理解でよいと思います。 (細かいところで実際と違う部分はありますが、この質問の本題とは関連ありません) > > 私のfsへの理解が間違っているのでしょうか? > > > `fs`も`XMLHttpRequest`のケースと全くおなじです。`fs.readFile()`とメインスレッドのコードに書かれているからといって、メインスレッドでファイルを読んでいるということにはなりません。JavaScriptのコードにはIOを行う能力はいっさいありませんから、`fs.readFile()` の実装は最終的にはCやC++で書かれたコードでOSに非同期ファイル読み込みか別スレッドでのファイル読み込みをリクエストしすぐに帰ってくるのだと思われます。`fs.readFile()` を呼んだコードの続きを実行したのち、ファイル読み込みが終わったらコールバックするのでしょう。