自從有了Node.js屯换,JavaScript也可以在服務(wù)器跑了,呵呵呵与学,代碼都是異步彤悔,實(shí)時高性能,爽的很索守,寫個文章介紹一下Node.js的知識晕窑。
什么是Node.js
Node.js 是一個基于 Chrome V8 引擎的 JavaScript 運(yùn)行環(huán)境。Node.js 使用了一個事件驅(qū)動卵佛、非阻塞式 I/O 的模型杨赤,使其輕量又高效。Allows you to build scalable network applications using JavaScript on the server-side.
可以用Node.js干什么
- Websocket Server:聊天室之類
- Fast File Upload Client:文件上傳服務(wù)
- Ad Server:廣告服務(wù)器
- 實(shí)時數(shù)據(jù)相關(guān)的應(yīng)用截汪,類似1
Node.js不是啥
- web框架:express是一個基于node.js的框架
- 應(yīng)用層: node.js非常底層疾牲,直接開發(fā)應(yīng)用應(yīng)該基于其他庫或者框架
- 多線程:node.js是單線程的(對于在上面跑的JavaScript應(yīng)用程序來說)
非阻塞式 I/O 的模型
Node.js可以寫出非阻塞的代碼
- 阻塞的代碼
var contents = fs.readFileSync('/etc/hosts');
console.log(contents);
console.log('Doing something else');
- 非阻塞的代碼
fs.readFile('/etc/hosts', function(err, contents) {
console.log(contents);
});
console.log('Doing something else');
非阻塞代碼是有一個回調(diào)函數(shù)。contents
在回調(diào)函數(shù)中才能拿到衙解,但是console.log('Doing something else');
不需要等到讀文件結(jié)束就可以打印了阳柔,這就是非阻塞式 I/O 的模型。
事件驅(qū)動
通過一個例子來說明事件驅(qū)動
hello world
var http = require('http');
http.createServer(function(request, response) {
response.writeHead(200);
response.write("Hello, world.");
response.end();
}).listen(8080, function() {
console.log('Listening on port 8080...');
});
上面的例子創(chuàng)建了一個http服務(wù)器蚓峦,返回helloworld問候舌剂。測試一下例子。
node hello.js 運(yùn)行上面的js
curl http://localhost:8080 訪問服務(wù)
curl命令說明
這個例子可以看出node.js是以事件驅(qū)動的暑椰〖艿看一下代碼中的回調(diào)是如何發(fā)生的。
在上圖中干茉,我們看到事件循環(huán)不斷檢查事件谴忧,當(dāng)發(fā)現(xiàn)有一個事件發(fā)生時,就調(diào)用回調(diào)函數(shù)角虫。
為了加深理解沾谓,我們深入到node.js核心去看看
- V8引擎解析JavaScript腳本。
- 解析后的代碼戳鹅,調(diào)用Node API均驶。
- libuv庫負(fù)責(zé)Node API的執(zhí)行。它將不同的任務(wù)分配給不同的線程枫虏,形成一個Event Loop(事件循環(huán))妇穴,以異步的方式將任務(wù)的執(zhí)行結(jié)果返回給V8引擎爬虱。
- V8引擎再將結(jié)果返回給用戶。
我們可以看到node.js的核心實(shí)際上是libuv這個庫腾它。這個庫是c寫的跑筝,它可以使用多線程技術(shù),而我們的Javascript應(yīng)用是單線程的瞒滴。
Node.js中的事件
所有事件的發(fā)生和這個類有關(guān)EventEmitter
我們看一個EventEmitter的代碼曲梗。
const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Insert a new listener in front
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// Prints:
// B
// A
emit
可以發(fā)出事件,on
可以監(jiān)聽事件妓忍。
我們再仔細(xì)分析一下helloworld.js的代碼:
-
http.createServer
的含義
http.createServer([requestListener])#
Returns a new instance of http.Server
.
The requestListener is a function which is automatically added to the 'request' event.
-
http.Server
是啥
Class: http.Server#
This class inherits from net.Server
and has the following additional events:(省略events虏两,可以點(diǎn)擊鏈接自行查看)
-
net.Server
是啥
Class: net.Server#
This class is used to create a TCP or local server.
net.Server is an EventEmitter with the following events:(省略events,可以點(diǎn)擊鏈接自行查看)
好世剖,我們知道EventEmitter是事件的基類定罢,也知道了如何查看node.js文檔。