核心模組
全域性物件與全域性變數
- node環境中,全域性物件為global;瀏覽器環境中,全域性物件時window
- 所有全域性變數均掛載在全域性物件上,作為全域性物件的屬性,其中包含:
- 顯式定義全域性物件的屬性
- 隱式定義的變數(沒有定義直接賦值的變數)
- 這裡建議使用 var、let、const 定義變數以避免引入全域性變數,因為全域性變數會汙染 名稱空間,提高程式碼的耦合風險。
常用的全域性變數
process:描述當前 Node.js 程式狀態 的物件,提供了一個與作業系統的簡單介面
- process.argv是命令列引數陣列,第一個元素是 node,第二個元素是指令碼檔名,從第三個元素開始每個元素是一個執行引數
- process.nextTick(callback)將callback放入非同步micro task佇列中,如果callback的執行時間需要很長,則通過這個方式可以不阻塞當前主執行緒 console:控制檯標準輸出
- console.log()常規輸出,也可以使用類似c語言printf()命令的佔位符輸出console.log('%d year', 1993)
- console.error()輸出錯誤
- console.trace()輸出當前呼叫棧
事件驅動 events模組
事件發射與監聽器:events.EventEmitter 物件
- EventEmitter.on(event, listener) 為指定事件註冊一個監聽器,接受一個字串event 和一個回撥函式listener
- EventEmitter.emit(event, [arg1], [arg2], [...]) 發射 event 事件,傳遞若干可選引數到事件監聽器的參數列
- EventEmitter.once(event, listener) 為指定事件註冊一個單次監聽器,即監聽器最多隻會觸發一次,觸發後立刻解除該監聽器
- EventEmitter.removeListener(event, listener) 移除指定事件的某個監聽器,listener 必須是該事件已經註冊過的監聽器
- EventEmitter.removeAllListeners([event]) 移除所有事件的所有監聽器, 如果指定 event,則移除指定事件的所有監聽器
var events = require('events'); var emitter = new events.EventEmitter(); emitter.on('event', function(arg1, arg2) { console.log('listener1', arg1, arg2); }); emitter.on('event', function(arg1, arg2) { console.log('listener2', arg1, arg2); }); emitter.emit('someEvent', 'hello', 'world'); // listener1 hello world // listener2 hello world 複製程式碼
大多數時候我們不會直接使用 EventEmitter,而是在物件中繼承它。包括 fs、net、 http 在內的,只要是支援事件響應的核心模組都是 EventEmitter 的子類,模組的例項物件可以直接使用on()方法監聽事件
檔案系統 fs模組
- fs.readFile() 非同步讀取檔案內容
- fs.readFileSync() 同步讀取檔案內容
- fs.open() 開啟檔案
- fs.read() 讀取檔案(從指定的檔案描述符 fd 中讀取資料並寫入 buffer 指向的緩衝區物件),需要先執行fs.open()開啟檔案後,在其回撥函式中使用fs.read().一般來說,除非必要,否則不要使用這種方式讀取檔案,因為它要求你手動管理緩衝區 和檔案指標,尤其是在你不知道檔案大小的時候,這將會是一件很麻煩的事情。
var fs = require('fs'); fs.open('content.txt', 'r', function(err, fd) { if (err) { console.error(err); return; } var buf = new Buffer(8); fs.read(fd, buf, 0, 8, null, function(err, bytesRead, buffer) { if (err) { console.error(err); return; } console.log('bytesRead: ' + bytesRead); console.log(buffer); }) }); // bytesRead: 8 // <Buffer 54 65 78 74 20 e6 96 87> 複製程式碼
HTTP 模組
HTTP模組封裝了一個HTTP伺服器與HTTP客戶端
HTTP伺服器(基於http.Server物件實現)
http.createServer()會建立一個http.Server例項物件
var http = require('http');
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<h1>Node.js</h1>');
res.end('<p>Hello World</p>');
}).listen(3000);
console.log("HTTP server is listening at port 3000.");
複製程式碼
http.createServer的回撥函式中的兩個引數 req 和res,分別是 http.ServerRequest和http.ServerResponse 的例項,表示請求和響應資訊
http.ServerRequest 是 HTTP 請求的資訊,所有的業務邏輯都是根據請求傳遞的內容展開的,所以是後端開發者最關注的內容
包含一些常用屬性:
http.ServerRequest的事件:- data :當請求體資料到來時,該事件被觸發。該事件提供一個引數 chunk,表示接 收到的資料。如果該事件沒有被監聽,那麼請求體將會被拋棄。該事件可能會被調 用多次
- end :當請求體資料傳輸完成時,該事件被觸發,此後將不會再有資料到來
- close: 使用者當前請求結束時,該事件被觸發
獲取GET請求內容:使用url.parse來解析get請求中url後面的引數
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(util.inspect(url.parse(req.url, true))); // util.inspect是將物件轉換成字串的工具函式
}).listen(3000);
複製程式碼
獲取POST請求內容
使用http.ServerRequest的data事件收集post請求體內容,然後使用querystring.parse來解析post請求傳過來的內容
var http = require('http');
var querystring = require('querystring');
var util = require('util');
http.createServer(function(req, res) {
var post = '';
req.on('data', function(chunk) {
post += chunk;
});
req.on('end', function() {
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);
複製程式碼
不要在真正的生產應用中使用上面這種簡單的方法來獲取 POST 請 求,因為它有嚴重的效率問題和安全問題,這只是一個幫助你理解的示例。
http.ServerResponse 是返回給客戶端的資訊,決定了使用者最終能看到的結果
三個重要的成員函式,用於返回響應頭、響應內容以及結束 請求:
- response.writeHead(statusCode, [headers]):向請求的客戶端傳送響應頭。 statusCode 是 HTTP 狀態碼,如 200 (請求成功)、404 (未找到)等。headers 是一個類似關聯陣列的物件,表示響應頭的每個屬性。該函式在一個請求內最多隻 能呼叫一次,如果不呼叫,則會自動生成一個響應頭
- response.write(data, [encoding]):向請求的客戶端傳送響應內容。data 是 一個 Buffer 或字串,表示要傳送的內容。如果 data 是字串,那麼需要指定 encoding 來說明它的編碼方式,預設是 utf-8。在 response.end 呼叫之前, response.write 可以被多次呼叫
- response.end([data], [encoding]):結束響應,告知客戶端所有傳送已經完 成。當所有要返回的內容傳送完畢的時候,該函式 必須 被呼叫一次。它接受兩個可 選引數,意義和 response.write 相同。如果不呼叫該函式,客戶端將永遠處於 等待狀態
HTTP 客戶端(作為客戶端向伺服器發起請求)
- http.request(options, callback) 發起 HTTP 請求
- option 是 一個類似關聯陣列的物件,表示請求的引數,callback 是請求的回撥函式
- callback 傳遞一個引數,為http.ClientResponse的例項
- http.request 返回一個http.ClientRequest的例項
var http = require('http'); var querystring = require('querystring'); var contents = querystring.stringify({ name: 'byvoid', email: 'byvoid@byvoid.com', address: 'Zijing 2#, Tsinghua University', }); var options = { host: 'www.byvoid.com', path: '/application/node/post.php', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length' : contents.length } }; var req = http.request(options, function(res) { res.setEncoding('utf8'); res.on('data', function (data) { console.log(data); }); }); req.write(contents); req.end(); // 不要忘了通過 req.end() 結束請求,否則伺服器將不會收到資訊 複製程式碼
- http.get(options, callback) get請求的簡化版,唯一的區別在於http.get 自動將請求方法設為了 GET 請求,同時不需要手動呼叫 req.end()
http.ClientRequest 物件(http.request()返回的例項物件)
物件含有的方法:
- write()伺服器傳送請求體
- end()寫結束以後必須呼叫 end 函式以通知伺服器,否則請求無效
http.ClientResponse 物件(http.request()回撥函式中的引數為該例項物件)
提供三個事件:
- data 資料達到是觸發
- end 資料傳輸結束後觸發
- close 連線結束後觸發
三個特殊的函式:
- response.setEncoding([encoding]):設定預設的編碼,當 data 事件被觸發時,資料將會以 encoding 編碼。預設值是 null,即不編碼,以 Buffer 的形式儲存。常用編碼為 utf8
- response.pause():暫停接收資料和傳送事件,方便實現下載功能
- response.resume():從暫停的狀態中恢復