Node.js 從小白到菜鳥(niǎo)系列文章記錄本人從一個(gè)小白到依靠 Node.js 混口飯吃的歷程。此篇為 Node.js 從小白到菜鳥(niǎo)系列文章的第一篇,記錄的 Node.js 服務(wù)端開(kāi)發(fā)常用的語(yǔ)言核心模塊使用方式。此篇文章內(nèi)容看不懂或記不住都沒(méi)關(guān)系,這僅僅是入門第一步,了解一下開(kāi)發(fā)中有哪些常用功能,可以使用 Node.js 提供的那些模塊來(lái)實(shí)現(xiàn)。
Crypto
Crypto 是 Node.js 提供的加密庫(kù),用來(lái)應(yīng)對(duì)開(kāi)發(fā)中嘗嘗需要的加密工作。常用的函數(shù)為 createHash()
計(jì)算哈希值,以下使用 md5
為例來(lái)展示 Crypto 常用方式。
// 計(jì)算 md5 值
const crypto = require('crypto'); // 引入 Crypto
function md5(data) {
return crypto
.createHash('md5') // 創(chuàng)建 md5 方法
.update(data, 'utf8') // 使用輸入數(shù)據(jù)計(jì)算哈希值,設(shè)置數(shù)據(jù)編碼為 utf8
.digest('hex'); // 結(jié)果為 16 進(jìn)制小寫的格式
}
console.log(md5('example string'));
以上示例代碼中,createHash()
為創(chuàng)建計(jì)算哈希值方法,這里使用了 md5
方法,可以根據(jù)需要設(shè)置為 sha1
等其他方法;update()
使用輸入數(shù)據(jù)計(jì)算哈希值,指定數(shù)據(jù)編碼方式為 utf8
,這里需要注意,如果沒(méi)有指定 utf8
數(shù)據(jù)編碼格式,最終計(jì)算出來(lái)的結(jié)果可能與其他編程語(yǔ)言計(jì)算出的結(jié)果不一致;digest()
為設(shè)置結(jié)果格式,這里使用了 16 禁止小寫的格式,可以根據(jù)需要設(shè)置為 base64
等其他格式。
更加具體的文檔可以參考 Node.js 官方文檔
File System
File System 為 Node.js 提供的文件系統(tǒng)操作方法。在服務(wù)端開(kāi)發(fā)過(guò)程中像記錄日志、讀取配置信息等工作都要涉及到文件的操作,以下簡(jiǎn)單介紹操作文件的幾種方法。
fs.stat()
獲取文件狀態(tài)
// 獲取文件狀態(tài)
const fs = require('fs');
fs.stat('./example.json', function (err, stat) {
if (err) {
return console.log(err);
}
console.log(stat);
console.log(stat.isDirectory());
console.log(stat.isFile());
});
// 獲取文件狀態(tài)報(bào)錯(cuò)結(jié)果
// { Error: ENOENT: no such file or directory, stat './example.json'
// errno: -2,
// code: 'ENOENT',
// syscall: 'stat',
// path: './example.json' }
// 獲取文件狀態(tài)正常結(jié)果
// Stats {
// dev: 16777220,
// mode: 33188,
// nlink: 1,
// uid: 501,
// gid: 20,
// rdev: 0,
// blksize: 4096,
// ino: 35186549,
// size: 3705,
// blocks: 8,
// atimeMs: 1503294130000,
// mtimeMs: 1503294128000,
// ctimeMs: 1503294128000,
// birthtimeMs: 1503293942000,
// atime: 2017-08-21T05:42:10.000Z,
// mtime: 2017-08-21T05:42:08.000Z,
// ctime: 2017-08-21T05:42:08.000Z,
// birthtime: 2017-08-21T05:39:02.000Z }
獲取文件狀態(tài)使用 fs.stat()
函數(shù),第一個(gè)參數(shù)是想要獲取狀態(tài)的文件地址,第二個(gè)參數(shù)是回調(diào)函數(shù)。返回的結(jié)果如上所示,當(dāng)文件不存在時(shí)會(huì)報(bào)錯(cuò),如果文件狀態(tài)正常獲取后會(huì)得到一個(gè) Object
代表文件的各屬性。在開(kāi)發(fā)中常用的一個(gè)操作是判斷給定地址是文件還是文件夾,這時(shí)可以使用 stat.isDirectory()
和 stat.isFile()
函數(shù)。stat.isDirectory()
在給定地址是文件夾時(shí)返回 true
否則返回 false
;stat.isFile()
在給定地址是文件時(shí)返回 true
否則返回 false
;
fs.readFile()
讀取文件內(nèi)容
fs.readFile('./example.json', {
encoding: 'utf8'
}, function (err, data) {
if (err) {
return console.log(err);
}
console.log(data);
});
fs.readFile()
第一個(gè)參數(shù)是想要獲取內(nèi)容的文件地址,第二個(gè)參數(shù)是附加參數(shù)對(duì)象,是可選參數(shù),這里設(shè)置了返回文件內(nèi)容編碼為 utf8
,第三個(gè)參數(shù)為回調(diào)函數(shù)。
fs.writeFile()
寫入文件內(nèi)容
const data = "Hello, world!";
fs.writeFile('./example.json', data, {
encoding: 'utf8'
}, function (err) {
if (err) {
return console.log(err);
}
return console.log('write content to file success');
});
fs.writeFile()
向文件中寫入內(nèi)容,新寫入的內(nèi)容會(huì)覆蓋原始文件的所有內(nèi)容。
fs.appendFile()
追加文件內(nèi)容
const data = "Hi!";
fs.appendFile('./example.json', data, {
encoding: 'utf8'
}, function (err) {
if (err) {
return console.log(err);
}
return console.log('append content to file success');
});
fs.appendFile()
向文件追加內(nèi)容,新內(nèi)容不會(huì)覆蓋原始文件內(nèi)容,會(huì)在原始內(nèi)容尾部添加新內(nèi)容。
更加具體的文檔可以參考 Node.js 官方文檔
Errors
Errors 是 Node.js 提供的錯(cuò)誤類,我們可以使用它創(chuàng)建錯(cuò)誤信息。
const EXAMPLE_ERROR_CODE = 404;
const err = new Error('example error message');
console.log(err);
err.code = EXAMPLE_ERROR_CODE;
console.log(err);
console.log(err.message);
console.log(err.code);
以上示例代碼創(chuàng)建了 message
為 example error message
,code
為 404
的一個(gè)錯(cuò)誤對(duì)象。
更加具體的文檔可以參考 Node.js 官方文檔
HTTP
HTTP 應(yīng)該是 Node.js 中最重要的一個(gè)模塊了,Node.js 服務(wù)端開(kāi)發(fā)都是基于 HTTP 模塊的。利用 HTTP 模塊創(chuàng)建 HTTP server 監(jiān)聽(tīng)某個(gè)端口等待客戶端的請(qǐng)求。下面以最常用的 Hello world!
示例來(lái)展示 Node.js HTTP 模塊的使用。
const http = require('http');
function handler(req, res) {
console.log(req.url);
res.write('Hello world!');
res.end();
}
const app = http.createServer(handler);
app.listen(3000, function () {
console.log('server listen on: 0.0.0.0:3000');
});
HTTP 最常用的是 http.createServer()
,http.createServer()
接受一個(gè)函數(shù)作為參數(shù),此函數(shù)第一個(gè)參數(shù)是 HTTP 請(qǐng)求對(duì)象,這里命名為 req
,第二個(gè)參數(shù)是 HTTP 響應(yīng)對(duì)象,這里命名為 res
。使用 req
獲取此次請(qǐng)求客戶端的數(shù)據(jù),使用 res
向客戶端響應(yīng)數(shù)據(jù)。示例中打印了客戶端請(qǐng)求的 URL,并向客戶端響應(yīng) Hello world!
。
http.createServer()
創(chuàng)建了一個(gè) HTTP server,我們還要設(shè)置監(jiān)聽(tīng)端口來(lái)啟動(dòng) HTTP server,示例中使用了 3000 端口,可以根據(jù)需要修改為任意合法的端口。
更加具體的文檔可以參考 Node.js 官方文檔
Path
Path 是 Node.js 提供的處理路徑的模塊,在開(kāi)發(fā)中獲取一個(gè)路徑的絕對(duì)路徑,計(jì)算兩個(gè)路徑的相對(duì)路徑等是很常見(jiàn)的需求。以下簡(jiǎn)單介紹幾個(gè)常用的路徑操作函數(shù)。
path.resolve()
獲取絕對(duì)路徑
const os = require('os');
const path = require('path');
function absolutePath(data) {
let result = path.resolve(data);
if (result.indexOf('~') !== -1) {
result = `${os.homedir()}${result.slice(result.indexOf('~') + 1)}`;
}
return result;
}
console.log(absolutePath('..'));
console.log(absolutePath('~/Desktop'));
path.resolve()
函數(shù)會(huì)返回輸入路徑的絕對(duì)路徑,這個(gè)絕對(duì)路徑依賴于用戶當(dāng)前的工作路徑(process.env.cwd()
)。path.resolve()
對(duì)于輸入格式為 ~/example_path
的路徑會(huì)直接拼接用戶當(dāng)前的工作路徑與 ~/example_path
,所以示例中的 absolutePaht()
在入戶輸入了 ~/example_path
時(shí)使用 os.homedir()
獲取到用戶的 home 路徑,然后與 path.resolve()
結(jié)果中 ~
后的部分拼接得到絕對(duì)路徑,很多獲取絕對(duì)路徑的包中也采用示例中的方式。
path.join()
拼接路徑
const path = require('path');
console.log(path.join(__dirname, '..', '..', 'example_path'));
path.join()
會(huì)將輸入的參數(shù)拼接成路徑,__dirname
是當(dāng)前代碼文件的絕對(duì)路徑,使用 path.join()
拼接路徑而不是 console.log(
${__dirname}/../../example_path)
是因?yàn)樵诓煌僮飨到y(tǒng)中路徑分隔符不同,Windows 操作系統(tǒng)中是 \
而 *nix 操作系統(tǒng)中是 /
,path.join()
或根據(jù)操作系統(tǒng)選擇爭(zhēng)取的分隔符。
更加具體的文檔可以參考 Node.js 官方文檔
總結(jié)
以上介紹的都是開(kāi)發(fā)中經(jīng)常用到的模塊,對(duì)于一個(gè)剛剛?cè)腴T的同學(xué)來(lái)說(shuō)記不住這些也沒(méi)關(guān)系,也不用死記硬背,對(duì)于目錄和各種功能有個(gè)印象即可。在開(kāi)發(fā)過(guò)程中根據(jù)需求需要用到哪些模塊時(shí)可以再回來(lái)查看或者直接參考 Node.js 官方文檔