目錄: Node.js核心入門(一)php
Node.js核心入門(二)html
fs 模塊是文件操做的封裝,它提供了文件的讀取、寫入、改名、刪除、遍歷目錄、連接等 POSIX 文件系統操做,且全部的方法都有異步和同步的形式。異步方法的最後一個參數都是一個回調函數。傳給回調函數的參數取決於具體方法,但回調函數的第一個參數都會保留給異常。若是操做成功完成,則第一個參數會是 null 或 undefined。node
const fs = require('fs');
fs.unlink('/tmp/hello', (err) => {
if (err) throw err;
console.log('成功刪除 /tmp/hello');
});
複製代碼
當使用同步方法時,任何異常都會被當即拋出。可使用 try/catch 來處理異常,或讓異常向上冒泡。後端
const fs = require('fs');
fs.unlinkSync('/tmp/hello');
console.log('成功刪除 /tmp/hello');
複製代碼
fs.readFile(path,[options], callback) 是最簡單的讀取。它接受一個必選參數filename,表示要讀取的文件名。第二個參數options是可選的,表示文件的字符編碼。callback是回調函數,用於接收文件的內容。若是不指定options,則 callback 就是第二個參數。回調函數提供兩個參數 err和data,err表示有沒有錯誤發生,data是文件內容。若是指定了options, data 是一個解析後的字符串,不然data將會是以Buffer形式表示的二進制數據。例如:數組
fs.readFile('/etc/passwd', 'utf8', callback);
複製代碼
須要注意的是,當path是一個目錄時,fs.readFile()與fs.readFileSync()的行爲與平臺有關。在 macOS、Linux 與Windows上,會返回一個錯誤。在 FreeBSD 上,會返回目錄內容的表示。緩存
// 在 macOS、Linux 與 Windows 上:
fs.readFile('<directory>', (err, data) => {
// => [Error: EISDIR: illegal operation on a directory, read <directory>]
});
// 在 FreeBSD 上:
fs.readFile('<directory>', (err, data) => {
// => null, <data>
});
複製代碼
fs.readFileSync(filename,[encoding])是fs.readFile 同步的版本。它接受的參數和fs.readFile相同,但讀取到的文件內容會以函數返回值的形式返回。若是有錯誤發生,fs 將會拋出異常,這時候咱們就須要使用 try 和catch 捕捉並處理異常。bash
fs.open(path, flags[, mode], callback)是POSIX open 函數的 封裝,與 C 語言標準庫中的fopen函數相似。它接受兩個必選參數,path 爲文件的路徑,而flags 能夠是如下值:服務器
'r' - 以讀取模式打開文件。若是文件不存在則發生異常。
'r+' - 以讀寫模式打開文件。若是文件不存在則發生異常。
'rs+' - 以同步讀寫模式打開文件。命令操做系統繞過本地文件系統緩存。
(這對 NFS 掛載模式下打開文件頗有用,由於它可讓你跳過潛在的舊本地緩存。 它對 I/O 的性能有明顯的影響,因此除非須要,不然不要使用此標誌。
注意,這不會使 fs.open() 進入同步阻塞調用。 若是那是你想要的,則應該使用 fs.openSync()。)
'w' - 以寫入模式打開文件。文件會被建立(若是文件不存在)或截斷(若是文件存在)。
'wx' - 相似 'w',但若是 path 存在,則失敗。
'w+' - 以讀寫模式打開文件。文件會被建立(若是文件不存在)或截斷(若是文件存在)。
'wx+' - 相似 'w+',但若是 path 存在,則失敗。
'a' - 以追加模式打開文件。若是文件不存在,則會被建立。
'ax' - 相似於 'a',但若是 path 存在,則失敗。
'a+' - 以讀取和追加模式打開文件。若是文件不存在,則會被建立。
'ax+' - 相似於 'a+',但若是 path 存在,則失敗。
複製代碼
mode 可設置文件模式(權限和 sticky 位),但只有當文件被建立時纔有效。默認爲 0o666,可讀寫。app
fs.read(fd, buffer, offset, length, position, callback) 是 POSIX read 函數的封裝,相比 fs.readFile 提供了更底層的接口。從fd指定的文件中讀取數據。buffer 是數據將被寫入到的 buffer。offset是buffer 中開始寫入的偏移量。length是一個整數,指定要讀取的字節數。position指定從文件中開始讀取的位置。若是position爲null,則數據從當前文件讀取位置開始讀取,且文件讀取位置會被更新。若是position爲一個整數,則文件讀取位置保持不變。回調有三個參數 (err, bytesRead, buffer)。異步
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>
複製代碼
Node.js 標準庫提供了http模塊,其中封裝了一個高效的 HTTP 服務器和一個簡易的HTTP 客戶端。 http.Server 是一個基於事件的 HTTP 服務器,它的核心由 Node.js 下層 C++ 部分實現,而接口由 JavaScript 封裝,兼顧了高性能與簡易性。 http.request則是一個HTTP 客戶端工具,用於向 HTTP 服務器發起請求,例如實現 Pingback或者內容抓取。
Node.js 中的HTTP接口被設計成支持協議的許多特性。好比,大塊編碼的消息。這些接口不緩衝完整的請求或響應,用戶可以以流的形式處理數據。HTTP消息頭由一個對象表示,其中鍵名是小寫的,鍵值不能修改:
{ 'content-length': '123',
'content-type': 'text/plain',
'connection': 'keep-alive',
'host': 'mysite.com',
'accept': '*/*' }
複製代碼
爲了支持各類可能的 HTTP 應用,Node.js的 HTTP API是很是底層的。它只涉及流處理與消息解析。它把一個消息解析成消息頭和消息主體,但不解析具體的消息頭或消息主體。鍵名是小寫的,鍵值不能修改。爲了支持各類可能的 HTTP 應用,Node.js 的 HTTP API 是很是底層的。 它只涉及流處理與消息解析。 它把一個消息解析成消息頭和消息主體,但不解析具體的消息頭或消息主體。
http.Server 是 http 模塊中的 HTTP 服務器對象,用 Node.js 作的全部基於 HTTP 協議的系統,如網站、社交應用甚至代理服務器,都是基於http.Server實現的。它提供了一套封裝級別很低的API,僅僅是流控制和簡單的學習解析,而全部的高級功能都是經過它的接口來實現的。好比官網上的這個例子:
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
})
複製代碼
在這段代碼中,就使用了http.createServer([requestListener])來新建一個的 http.Server 實例。如今就先讓咱們來看看http.createServer([requestListener])吧。
http.Server 是一個基於事件的 HTTP 服務器,全部的請求都被封裝爲獨立的事件,開發者只須要對它的事件編寫響應函數便可實現 HTTP 服務器的全部功能。它繼承自 EventEmitter ,提供瞭如下幾個事件:
在這些事件最經常使用的是request是最經常使用的,所以 http 提供了一個捷徑: http.createServer([requestListener]) ,功能是建立一個 HTTP 服務器並將requestListener 做爲 request 事件的監聽函數。咱們上面那個官網的例子就是如此,其實它顯式的實現方法是這樣的:
//httpserver.js
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = new http.Server();
server.on('request', (req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
})
複製代碼
http.ServerRequest 是 HTTP 請求的信息,是後端開發者最關注的內容。它通常由http.Server 的 request 事件發送,做爲第一個參數傳遞,一般簡稱 request 或 HTTP 請求通常能夠分爲兩部分:請求頭(Request Header)和請求體(Requset Body)。以上內容因爲長度較短均可以在請求頭解析完成後當即讀取。而請求體可能相對較長,須要必定的時間傳輸,所以 http.ServerRequest 提供瞭如下3個事件用於控制請求體傳輸。req。HTTP請求通常能夠分爲兩部分:請求頭(RequestHeader)和請求體(RequsetBody)。以上內容因爲長度較短均可以在請求頭解析完成後當即讀取。而請求體可能相對較長,須要必定的時間傳輸,所以http.ServerRequest提供瞭如下3個事件用於控制請求體傳輸。http.ServerRequest提供了3個事件用於控制請求體傳輸:
data:當請求體數據到來時,該事件被觸發,提供一個參數給回調函數,是接受到的數據,該事件可能被屢次調用(全部data按順序的集合,是請求體數據)。若是該事件沒有被監聽,請求體將被拋棄;
end:當請求體數據完成時該事件觸發。此後再也不觸發data事件;
close:用戶當前請求結束時,該事件被觸發。不一樣於end,若是用戶強制終止了傳輸,也仍是調用close。
表4-2 ServerRequest 的屬性
名 稱 含 義
complete 客戶端請求是否已經發送完成
httpVersion HTTP 協議版本,一般是 1.0 或 1.1
method HTTP 請求方法,如 GET、POST、PUT、DELETE 等
url 原始的請求路徑,例如 /static/image/x.jpg 或 /user?name=byvoid
headers HTTP 請求頭
trailers HTTP 請求尾(不常見)
connection 當前 HTTP 鏈接套接字,爲 net.Socket 的實例
socket connection 屬性的別名
client client 屬性的別名
複製代碼
注意, http.ServerRequest 提供的屬性中沒有相似於 PHP 語言中的 _POST 的屬性,GET請求被直接內嵌在路徑中。URL是完整的請求路徑(包括?後面的部分),所以手動解析後面的內容做爲GET請求的參數。Node.js的url模塊中的parse函數提供了這個功能。
以url:http://127.0.0.1/user?name=byvoid&email=byvoid@byvoid.com爲例:
var http = require("http");
var url = require("url");
var server = new http.Server();
server.on("request", function (req, res) {
if (req.url == "/favicon.ico") {
return;
}
var m = url.parse(req.url, true);
console.log(m)
res.writeHead(200, {'Content-type': 'text/html;charset = utf8'});
res.end();
})
server.listen(80);
console.log("The server begin");
複製代碼
console.log輸出內容:
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search:'?name=byvoid&email=byvoid@byvoid.com',
query: { name: 'byvoid', email:'byvoid@byvoid.com' },
pathname: '/user',
path:'/user?name=byvoid&email=byvoid@byvoid.com',
href:'/user?name=byvoid&email=byvoid@byvoid.com'
}
複製代碼
HTTP 協議1.1版本提供了8種標準的請求方法,而其中最多見的就是 GET 和 POST。相比GET請求把全部的內容編碼到訪問路徑中,POST 請求的內容所有都在請求體中。http.ServerRequest 並無一個屬性內容是在請求體中,緣由是等待請求體傳輸多是一件耗時的工做,譬如上傳文件。而不少時候咱們可能並不須要理會請求體的內容,且惡意的 POST 請求會大大消耗服務器的資源。因此 Node.js 默認是不會解析請求體的,所以當咱們須要的時候,咱們就要手寫一個,具體實現方法以下:
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);
複製代碼
http.ServerResponse 是返回給客戶端的信息,決定了用戶最終能看到的結果。它也是由 http.Server 的 request 事件發送的,做爲第二個參數傳遞,通常簡稱爲 response 或 res 。http.ServerResponse 有三個重要的成員函數,用於返回響應頭、響應內容以及結束請求:
http 模塊提供了兩個函數 http.request和http.get,功能是做爲客戶端向HTTP服務器發起請求。
http.request(options,callback)發起HTTP請求,它接受兩個參數,option是一個相似關聯數組的對象,表示請求的參數,callback是請求的回調函數。option經常使用的參數以下所示:
而callback 則傳遞一個參數,爲 http.ClientResponse 的實例。http.request 返回一個http.ClientRequest 的實例,下面是一個經過 http.request 發送 POST 請求的代碼:
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();
複製代碼
運行結果以下:
array(3) {
["name"]=>
string(6) "byvoid"
["email"]=>
string(17) "byvoid@byvoid.com"
["address"]=>
string(30) "Zijing 2#, Tsinghua University"
}
複製代碼
http 模塊還提供了一個更加簡便的方法用於處理GET請求:http.get(options, callback)。它是http.request的簡化版,惟一的區別在於http.get自動將請求方法設爲了 GET 請求,同時不須要手動調用 req.end() :
var http = require('http');
http.get({host: 'www.byvoid.com'}, function(res) {
res.setEncoding('utf8');
res.on('data', function (data) {
console.log(data);
});
});
複製代碼
該對象在 http.request() 內部被建立並返回。它表示着一個正在處理的請求,其請求頭已進入隊列。它提供一個response事件,即http.request或http.get第二個參數指定的回調函數的綁定對象。
var http = require('http');
var req = http.get({host: 'www.byvoid.com'});
req.on('response', function(res) {
res.setEncoding('utf8');
res.on('data', function (data) {
console.log(data);
});
});
複製代碼
http.ClientRequest像http.ServerResponse同樣也提供了 write 和 end 函數,用於向服務器發送請求體,一般用於 POST、PUT 等操做。全部寫結束之後必須調用end函數以通知服務器,不然請求無效。http.ClientRequest 還提供瞭如下經常使用的函數:
http.ClientResponse 與 http.ServerRequest類似,提供了三個事件data、end和 close,分別在數據到達、傳輸結束和鏈接結束時觸發,其中data 事件傳遞一個參數chunk,表示接收到的數據。
http.ClientResponse 也提供了一些屬性,用於表示請求的結果狀態:
statusCode HTTP 狀態碼,如 200、40四、500
httpVersion HTTP 協議版本,一般是 1.0 或 1.1
headers HTTP 請求頭
trailers HTTP 請求尾(不常見)
複製代碼
http.ClientResponse 還提供瞭如下幾個特殊的函數: