问题描述:大家都知道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
node是單線程的沒錯,可以把這個線程理解為主線程,當遇到異步時,會把文件讀取異步的任務交給底層的libuv,會根據平台選擇(文件IO採用線程池,網絡IO,linux採用epoll,windows採用IOCP)只是執行js程式碼的是單執行緒而已,非同步任務完成後會放進事件佇列,事件輪詢,等到主執行緒空閒時取出來處理。
大家讲道理2017-04-17 16:14:59
其實題主只要在網路上搜一下node event loop
的機制就能明白node的非同步是怎麼運作的了。 node event loop
的机制就能明白node的异步是怎么工作的了。
node底层有一个叫做libuv
的东西,它与c/c++做交互,比如I/O,网络请求等等。
大概说下event loop的机制,题主最好网上搜下,深入理解下。
比如你写的例子:
1. var fs = require("fs");
2. fs.readFile('input.txt', 4. function (err, data) {//异步执行,这个地方没有等待执行结束就已经打印了"程序执行结束",然后打印data数据
if (err) return console.error(err);
console.log(data.toString());
});
3. console.log("程序执行结束!");
方便介绍,我标上了序号。它的工作机制大概是这样的:
程序运行到 1
处。引用完之后继续走,到了2
处,node发现是一个异步的I/O操作,总所周知I/O操作是巨费资源的,node是单线程它真的不想干这个事情,所以呢,它就交给了libuv
,并给了它一个回调函数,也就是标4
的那个地方,这个回调就是在c/c++底层处理完之后,libuv就会去调用这个回调。
但在交给libuv的过程,程序是一直往下面运行的,也就到了3
的地方,打印。
这就是为什么先看到打印结果后看到文件内容。
这也大概是Event Loop
的工作机制,node一直把难搞的交给别人去搞,等别人搞完了,只执行一个回调而已。所以说node不适合做大量计算的工作,比如你写个while(true){}
node底層有一個叫做libuv
的東西,它與c/c++做交互,像是I/O,網路請求等等。
1
處。引用完之後繼續走,到了2
處,node發現是一個異步的I/O操作,總所周知I/O操作是巨費資源的,node是單線程它真的不想幹這個事情,所以呢,它就交給了libuv
,並給了它一個回調函數,也就是標4
的那個地方,這個回調就是在c/c++底層處理完之後,libuv就會去呼叫這個回呼。 🎜但在交給libuv的過程,程式是一直往下面運行的,也就到了3
的地方,列印。 🎜這就是為什麼先看到列印結果後看到文件內容。 🎜
🎜這也大概是Event Loop
的工作機制,node一直把難搞的交給別人去搞,等別人搞完了,只執行一個回調而已。所以說node不適合做大量計算的工作,像是你寫個while(true){}
整個程式就蹦了。 🎜node就是喜歡小計算多並發,它處理起來真的有優勢,不服不行。 🎜怪我咯2017-04-17 16:14:59
我說下我的假設,
假設讀取一個文件,NODEJS發送一個讀取信號(可能是發送其他什麼東西,原理一樣)給操作系統,此時NodeJS去幹別的事了(不用等待操作系統讀取檔案完畢,這就是非同步),作業系統讀取完畢後,發送一個事件給NodeJs,NodeJs就知道檔案讀取完畢,透過回呼函數回呼執行結果。
讀取檔案的等待時間NodeJs拿來做別的事了,沒有阻塞。
巴扎黑2017-04-17 16:14:59
下面的那個如果等待讀取文件結束然後再打印下面的程序执行结束
,那这和同步模式有啥区别吗………… nodejs
是單線程的沒錯,這裡之所以下面的先打印出來了,因為是主進程結束之後再進行異步進程。
PHP中文网2017-04-17 16:14:59
node的引擎是單線程的沒錯 但是他底層調用的libuv不是啊 libuv在linux上網絡請求用的epoll 文件讀取是自己建了個線程池 在windows上面用的iocp