Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.html
Node.js是一個基於Google Chrome的V8引擎的JavaScript運行環境,它容許使用JavaScript語言編寫服務器端代碼。Node.js具備事件驅動和I/O非阻塞兩大特色,輕量而高效。node
官網地址webpack
從官網下載最新版本的Node.js,直接安裝。安裝時選擇所有組件,並添加到環境變量Path中。web
運行命令:node -v
查看是否安裝成功。算法
運行命令:node
進入到node.js的交互環境,能夠輸入任意JavaScript語句,並查看運行結果。數據庫
運行命令:node <*.js>
直接執行js文件裏的內容。express
運行命令:node --use_strict <*.js>
爲js文件開啓嚴格模式。npm
安裝Node.js的時候,會自動安裝包管理工具npm。後端
運行命令:npm -v
查看npm的版本。api
命令行模式會一次性執行js文件,中間沒有交互;交互模式則是每一行單獨執行,能夠進行交互。
若是不想使用集成的IDE,可使用VS Code編輯器進行Node.js的開發和調試。具體操做和配置能夠參照VS Code的官網教程。
Node.js Applications with VS Code
在Node.js環境中,一個js文件就稱之爲一個模塊。使用模塊提升了代碼的可維護性以及可重用性,還避免了函數名和變量名衝突。
當在模塊中定義一個對象(對象、函數、數組等)時,能夠輸出這個對象以供其餘模塊使用:
module.exports = object_name;
其餘模塊要想使用這個對象,能夠在模塊中引入該對象:
var variable_name = require('/path/to/the/module/module_name');
Tips:若是不指定路徑,Node會按照內置模塊、全局模塊、當前模塊的順序進行查找。
在瀏覽器中,JavaScript有一個全局對象window;而在Node.js環境中,也有一個全局對象global。因爲JavaScript代碼既能在瀏覽器執行,也能在Node環境下執行,能夠經過全局對象名稱來判斷JavaScript代碼是在哪一個環境下執行的。
process也是Node.js提供的一個對象,表示當前Node.js進程,進程自己的事件由process來處理。
fs模塊是文件系統模塊,負責文件的讀寫操做,提供了同步和異步兩種方法。大部分做爲服務端的代碼,必須使用異步代碼。可是在服務器啓動時讀取配置文件,或結束時寫入狀態等操做,由於這些代碼只執行一次,因此可使用同步方法。
讀文本文件:
var fs = require('fs'); fs.readFile('input.txt', 'utf-8', function (err, data) { if (err) { console.log(err); } else { console.log(data); } });
其中,readFile函數的第一個參數是文件名,第二個參數是文件編碼,第三個參數是一個回調函數。回調函數的第一個參數表明錯誤信息,第二個參數表明返回結果。
讀二進制文件:
var fs = require('fs'); fs.readFile('input.png', function (err, data) { if (err) { console.log(err); } else { console.log(data); console.log(data.length + ' bytes'); } });
其中,不須要文件編碼,而且回調函數的data參數將返回一個Buffer對象。Buffer對象是一個包含零個或任意個字節的數組。
寫文件:
var fs = require('fs'); var data = 'Hello world'; fs.writeFile('output.txt', data, function (err) { if (err) { console.log(err); } else { console.log('success'); } });
其中,writeFile函數的第一個參數是文件名,第二個參數是要寫入的數據,第三個參數是回調函數。
讀取文件的相關信息:
fs.stat('input.txt', function (err, stat) { ... });
stream是一個只能在服務端使用的模塊,用來支持流數據結構,流中的數據是有序的。流是一個對象,使用時只需關注流的事件便可。data事件表示流的數據能夠讀取,end事件表示流沒有數據能夠讀取,error事件表示出現錯誤。
讀文件:
var fs = require('fs'); var rs = fs.createReadStream('input.txt', 'utf-8'); rs.on('data', function (chunk) { console.log('DATA:'); console.log(chunk); }); rs.on('end', function () { console.log('END'); }); rs.on('error', function (err) { console.log('ERROR: ' + err); });
寫文件:
var fs = require('fs'); var ws1 = fs.createWriteStream('output1.txt', 'utf-8'); ws1.write('使用Stream寫入文本數據...\n'); ws1.write('END.'); ws1.end(); var ws2 = fs.createWriteStream('output2.txt'); ws2.write(new Buffer('使用Stream寫入二進制數據...\n', 'utf-8')); ws2.write(new Buffer('END.', 'utf-8')); ws2.end();
可使用管道操做pipe將讀取流和寫入流串聯起來:
var fs = require('fs'); var rs = fs.createReadStream('input.txt'); var ws = fs.createWriteStream('output.txt'); rs.pipe(ws);
默認狀況下,當讀取流的數據讀取完畢,會觸發end事件,並自動關閉寫入流。若是不想關閉,須要傳遞額外的參數。
readable.pipe(writable, { end: false });
http模塊是web應用最經常使用的一個模塊,提供了request和response對象。request對象封裝HTTP請求,調用request對象的屬性和方法,能夠獲取HTTP請求的全部信息;response對象封裝HTTP響應,調用response對象的方法,能夠把HTTP響應返回給瀏覽器。
var http = require('http'); var server = http.createServer(function (request, response) { // 獲取HTTP請求的method和url console.log(request.method + ':' + request.url); // 將HTTP響應的內容寫入response response.writeHead(200, {'Content-Type': 'text/html'}); response.end('<h1>Hello world!</h1>'); }); // 監聽8080端口 server.listen(8080);
url模塊能夠用來將URL字符串解析成一個Url對象,從而獲取想要的信息。
var url = require('url'); console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));
path模塊能夠用來處理本地文件目錄。
var path = require('path'); // 解析當前目錄 var workDir = path.resolve('.'); // 組合完整的文件路徑 var filePath = path.join(workDir, 'pub', 'index.html');
crypto模塊提供通用的加密和哈希算法。
MD5哈希算法用來給任意數據一個簽名,一般用一個十六進制字符串表示:
const crypto = require('crypto'); const hash = crypto.createHash('md5'); hash.update('Hello, world!'); console.log(hash.digest('hex'));
Hmac哈希算法能夠利用MD5等算法,另外還須要一個密鑰:
const crypto = require('crypto'); const hmac = crypto.createHmac('sha256', 'secret-key'); hmac.update('Hello, world!'); console.log(hmac.digest('hex'));
AES是一種經常使用的對稱加密算法,加密與解密使用同一個密鑰。crypto模塊提供了AES支持,但須要自行封裝。DiffieHellman算法是一種密鑰交換協議,可讓雙方自行協商一個密鑰。crypto模塊還能夠處理數字證書。
使用Node.js開發Web服務器端,有幾點好處:
針對Node.js,出現了不少後端相關的Web框架、ORM框架、模板引擎、測試框架、構建工具等。
Express是第一代最流行的Web服務端框架,它對Node.js的http進行了封裝。雖然Express的API很是簡單,可是因爲是基於ES5,要實現異步,只能使用回調。若是異步嵌套層次過多,代碼很難理解。
var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World!'); }); app.listen(3000, function () { console.log('Example app listening on port 3000!'); });
koa1基於ES6,使用generator實現異步。雖然使用generator在寫法上比回調簡單,但其本意並非用於異步。真正設計用來實現異步的是Promise,但Promise的寫法過於複雜。
var koa = require('koa'); var app = koa(); app.use('/test', function *() { yield doReadFile1(); var data = yield doReadFile2(); this.body = data; }); app.listen(3000);
koa2基於ES7,使用Promise和關鍵字async
配合實現異步,同時兼容generator的寫法。
app.use(async (ctx, next) => { await next(); var data = await doReadFile(); ctx.response.type = 'text/plain'; ctx.response.body = data; });
ORM技術是將關係型數據庫的表結構映射到對象上,Sequelize返回Promise對象,能夠更好地進行異步處理。
ES6:
Pet.findAll() .then(function (pets) { for (let pet in pets) { console.log(`${pet.id}: ${pet.name}`); } }).catch(function (err) { // error });
ES7:
(async () => { var pets = await Pet.findAll(); })();
要想使用Sequelize操做數據庫,首先須要建立一個Sequelize實例。而後定義數據模型Model,使用Sequelize映射數據庫表。這樣就能夠調用實例的相應方法來對數據庫進行操做。
Sequelize操做數據庫的通常步驟:
Node.js默認使用Jade做爲模板引擎(現更名爲Pug)。Jade是Node.js的一個模塊,jade文件能夠被預編譯爲.js文件,也能夠被編譯爲目標html代碼。
Mocha是JavaScript的單元測試框架,既能夠在瀏覽器環境運行,也能夠在Node.js的環境運行。
特色:
WebSocket利用HTTP協議創建鏈接,在瀏覽器和服務器之間創建雙向通訊的通道,服務器能夠主動向瀏覽器發送消息,而不須要經過瀏覽器發送請求。
首先,WebSocket鏈接必須由瀏覽器發起,由於請求協議是一個標準的HTTP請求。
GET ws://localhost:3000/ws/chat HTTP/1.1 Host: localhost Upgrade: websocket Connection: Upgrade Origin: http://localhost:3000 Sec-WebSocket-Key: client-random-string Sec-WebSocket-Version: 13
與普通HTTP請求的區別:
ws://
開頭Upgrade: websocket
和Connection: Upgrade
表示鏈接將被轉換爲WebSocket鏈接Sec-WebSocket-Key
用於標識這個鏈接Sec-WebSocket-Version
指定WebSocket的協議版本而後,若是服務器接受請求,會返回響應:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: server-random-string
其中,響應碼101表示將切換協議,切換後的協議經過Upgrade來指定。
在Node.js中,最經常使用的WebSocket模塊是ws。建立一個WebSocket的服務器實例:
const WebSocket = require('ws'); const WebSocketServer = WebSocket.Server; const wss = new WebSocketServer({ port: 3000 });
若是有WebSocket請求接入,wss對象能夠響應connection事件來處理這個WebSocket。對於每一個WebSocket鏈接,都要對它綁定某些事件方法來處理不一樣的事件。
參考文章:
廖雪峯:Node.js教程