问题描述:大家都知道nodejs因为其异步编程和事件机制而被大家津津乐道,但是最近在学习nodejs时对nodejs的异步不是很理解。都说nodejs是单进程单线程的,但是它的异步处理又给人的感觉是多线程的,比如下面的例子:
var fs = require("fs");
var data = fs.readFileSync('input.txt');//同步等待执行,这必然是单线程
console.log(data.toString());
console.log("程序执行结束!");
但是,它还有异步方式是这样处理:
var fs = require("fs");
fs.readFile('input.txt', function (err, data) {//异步执行,这个地方没有等待执行结束就已经打印了"程序执行结束",然后打印data数据
if (err) return console.error(err);
console.log(data.toString());
});
console.log("程序执行结束!");
希望大神们帮忙解释一下,总感觉它异步是多线程方式,而nodejs确实单进程单线程的?
巴扎黑2017-04-17 16:14:59
ノードはシングルスレッドです。非同期が発生すると、ファイルを読み取る非同期タスクが基盤となる libuv に渡され、プラットフォーム (ファイル IO) に応じて選択されます。スレッド プールを使用し、ネットワーク IO、Linux は epoll、Windows は IOCP を使用します) 非同期タスクが完了すると、js コードのみが単一のスレッドで実行され、イベント キューに入れられ、イベント ポーリングが取得されます。メインスレッドがアイドル状態のときに処理のために出力されます。
大家讲道理2017-04-17 16:14:59
実際、質問者はインターネット上でnode event loop
の仕組みを検索することで、ノードの非同期動作がどのように動作するのかを理解することができます。
ノードの下部には libuv
と呼ばれるものがあり、I/O やネットワーク リクエストなどの C/C++ と対話します。
イベントループの仕組みについては、質問者がネットで調べて詳しく理解するのが一番です。
たとえば、あなたが書いた例:
リーリー紹介の便宜上、シリアル番号をマークしました。その動作メカニズムは大まかに次のとおりです:
プログラムは 1
まで実行されます。引用後、歩き続けます。 2
に到達すると、ノードはそれが非同期 I/O 操作であることがわかります。ノードはシングルスレッドであり、実際にはそれを必要としません。これを行うには、 libuv
に渡され、 4
とマークされた場所にコールバック関数が与えられます。 このコールバックは、C/C++ の最下層が実行された後に libuv によって呼び出されます。加工された。
しかし、それを libuv に渡す過程で、プログラムは下向きに実行され続け、印刷のために 3
の場所に到達します。
これが、最初に印刷結果が表示され、次にファイルの内容が表示される理由です。
これはおそらく Event Loop
の動作メカニズムです。ノードは常に難しいタスクを他の人に任せ、他の人が完了した後にのみコールバックを実行します。したがって、ノードは大量の計算作業を行うのには適していません。たとえば、while(true){}
を記述すると、プログラム全体がクラッシュします。
Node は小規模な計算と高い同時実行性を好みます。私はそれを受け入れずにはいられません。
怪我咯2017-04-17 16:14:59
私の仮説について話しましょう。
ファイルを読み取るときに、NODEJS がオペレーティング システムに読み取り信号を送信するとします (原理は同じです)。その他 (オペレーティング システムがファイルの読み取りを完了するまで待つ必要はありません。これは非同期です)。オペレーティング システムが読み取りを完了すると、NodeJ にイベントが送信され、ファイルが読み取られたことが認識され、コールバックされます。コールバック関数による実行結果。
NodeJs は、ファイルの読み取りの待機時間を利用して、ブロックせずに他の処理を実行します。
巴扎黑2017-04-17 16:14:59
以下のものがファイルの読み取りの終了を待ってから次の 程序执行结束
を出力する場合、これと同期モードの間に違いはありますか... nodejs
はシングルスレッドです、はい、その理由は、メインプロセスが終了した後に非同期プロセスが開始されるため、以下が最初に出力されます。
PHP中文网2017-04-17 16:14:59
ノードのエンジンはシングルスレッドですが、下位で呼び出される libuv はシングルスレッドではありません。Linux 上のネットワーク リクエストに使用される epoll は、独自のスレッド プールを構築し、Windows 上で iocp を使用します。