1. 程式人生 > 其它 >Node.js-COMMONJS 規範

Node.js-COMMONJS 規範

ECMAScript 標準的缺陷

沒有模組系統
標準庫較少
沒有標準介面
缺乏管理系統

模組化

如果程式設計的規模達到了一定程度,則必須對其進行模組化 。

模組化 可以有多種形式,但至少 應該 提供能夠將程式碼分割為多個原始檔的機制 。

CommonJS 的模組 功能可以幫我們解決該問題。

CommonJS 規範

CommonJS 規範的提出,主要是為了彌補當
前 JavaScript 沒有 模組化 標準 的 缺陷 。
CommonJS 規範為 JS 指定了一個美好的願景,
希望 JS 能夠在任何地方執行 。
CommonJS 對模組的定義十分簡單:
– 模組引用
– 模組定義
– 模組標識

模組 引用

在規範中,定義了 require() 方法,這個方
法接手模組標識,以此將一個模組引入到
當前執行環境中。
模組引用的示例程式碼:
– var math = require('math');

模組定義

在執行環境中,提供了 exports 物件用於導
出當前模組的方法或者變數,並且它是唯
一的匯出的出口。
在模組中還存在一個 module 物件,它代表
模組自身,而 exports 是 module 的屬性。
在 Node 中一個檔案就是一個模組。

模組定義

exports . xxx = function () {};
module . exports = {} ;

模組標識

模組 標識 其實就是模組的名字,也就是傳
遞給 require() 方法的引數,它必須是符合
駝峰命名法的字串,或者是以 .、 .. 開頭的
相對路徑、或者絕對路徑。
模組的定義十分簡單,介面也十分簡潔。
每個模組具有獨立的空間,它們互不干擾,
在引用時也顯得乾淨利落。

Node 的模組實現

Node 中雖然使用的是 CommonJS 規範,但是
其自身也對規範做了一些取捨。
在 Node 中引入模組,需要經歷如下 3 個步驟:
– 路徑分析
– 檔案定位
– 編譯執行
在 Node 中,模組分為 三 類:一類是底層由
C++ 編寫的 內建模組 ,一類是 Node 提供的 核
心模組 ;還有一類是使用者編寫的模組,稱為 文
件模組 。前端培訓

包 package

CommonJS 的包規範允許我們將一組相關
的模組組合到一起,形成一組完整的工具。
CommonJS 的包規範由 包結構 和 包描述文
件 兩個部分組成。
包結構
– 用於組織包中的各種檔案
包描述檔案
– 描述包的相關資訊,以供外部讀取分析

包結構

包實際上就是一個壓縮檔案,解壓以後還
原為目錄。符合規範的目錄,應該包含如
下檔案:
– package.json 描述檔案
– bin 可執行二進位制檔案
– lib js 程式碼
– doc 文件
– test 單元測試

包描述檔案

包描述檔案用於表達非程式碼相關的資訊,
它是一個 JSON 格式的檔案 – package.json ,
位於包的根目錄下,是包的重要組成部分。
package.json 中的欄位
– name 、 description 、 version 、 keywords 、
maintainers 、 contributors 、 bugs 、
licenses 、 repositories 、 dependencies 、
homepage 、 os 、 cpu 、 engine 、 builtin 、
directories 、 implements 、 scripts 、 author 、
bin 、 main 、 devDependencies 。

NPM(Node Package Manager)

CommonJS 包規範是理論, NPM 是其中一
種實踐。
對於 Node 而言, NPM 幫助其完成了第三
方模組的釋出、安裝和依賴等。藉助 NPM ,
Node 與第三方模組之間形成了很好的一個
生態系統。

NPM 命令

npm – v– 檢視版本
npm– 幫助說明
npm search 包名– 搜尋模組包
npm install 包名– 在當前目錄安裝 包
npm install 包名 – g– 全域性模式安裝 包

npm remove 包名– 刪除一個 模組

npm install 檔案路徑– 從本地安裝

npm install 包名 – registry= 地址– 從映象源安裝

npm config set registry 地址– 設定映象源

Buffer( 緩衝區 )

從結構上看 Buffer 非常像一個數組,它的元
素為 16 進位制的兩位數。
實際上一個元素就表示記憶體中的一個位元組。
實際上 Buffer 中的記憶體不是通過 JavaScript
分配的,而是在底層通過 C++ 申請的。
也就是我們可以直接通過 Buffer 來建立記憶體
中的空間。

Buffer 的操作

使用 Buffer 儲存字串
建立指定大小的 Buffer 物件
let str = " 你好 atguigu";
let buf = Buffer.from(str , "utf -8") ;
let buf3 = Buffer.alloc( 1024*8 )

Buffer 的轉換

Buffer 與字串間的轉換
– 支援的編碼 :
ASCII 、 UTF - 8 、 UTF - 16LE/UCS - 2 、 Base64 、
Binary 、 Hex
– 字串轉 Buffer
Buffer.from(str , [encoding]);
– Buffer 轉字串
buf.toString([encoding] , [start] , [end]);

寫入操作

向緩衝區中寫入字串
– buf.write(string [, offset[, length]][, encoding ])
替換指定索引位置的資料
– buf[index ]
將指定值填入到緩衝區的指定位置
– buf.fill(value [, offset[, end]][, encoding ])

讀取 操作

將緩衝區中的內容,轉換為一個字串返回
– buf.toString ([encoding[, start[, end ]]])
讀取緩衝區指定索引的內容
– buf[index ]

其他操作

複製緩衝區
– buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
對緩衝區切片
– buf.slice([start[, end ]])
拼接緩衝區
– Buffer.concat(list[, totalLength])

fs (檔案系統)

在 Node 中,與檔案系統的互動是非常重要
的,伺服器的本質就將本地的檔案傳送給
遠端的客戶端
Node 通過 fs 模組來和檔案系統進行互動
該模組提供了一些標準檔案訪問 API 來開啟、
讀取、寫入檔案,以及與其互動。
要使用 fs 模組,首先需要對其進行載入
– const fs = require("fs");

同步和非同步呼叫

fs 模組中所有的操作都有兩種形式可供選擇
同步 和 非同步 。
同步檔案系統會 阻塞 程式的執行,也就是
除非操作完畢,否則不會向下執行程式碼。
非同步檔案系統 不會阻塞 程式的執行,而是
在操作完成時,通過回撥函式將結果返回。

開啟和關閉檔案

開啟檔案
– fs.open(path, flags[, mode], callback )
– fs.openSync(path, flags[, mode])
關閉檔案
– fs.close(fd, callback )
– fs.closeSync(fd)

開啟狀態

寫入檔案

fs 中提供了四種不同的方式將資料寫入檔案
– 簡單檔案寫入
– 同步檔案寫入
– 非同步檔案寫入
– 流式檔案寫入

簡單檔案 寫入

fs.writeFile(file , data[, options], callback )
fs.writeFileSync(file, data[, options ])
引數:
– file 檔案路徑
– data 被寫入的內容,可以是 String 或 Buffer
– options 物件,包含屬性( encoding 、 mode 、
flag )
– callback 回撥函式

同步檔案寫入

fs.writeSync(fd, buffer, offset, length[, position ])
fs.writeSync(fd, data[, position[, encoding ]])
要完成同步寫入檔案,先需要通過 openSync() 開啟檔案來獲取
一個檔案描述符,然後在通過 writeSync() 寫入檔案。
引數
– fd 檔案描述符,通過 openSync() 獲取
– data 要寫入的資料( String 或 Buffer )
– offset buffer 寫入的偏移量
– length 寫入的長度
– position 寫入的起始位置
– encoding 寫入編碼

非同步檔案寫入

fs.write(fd, buffer, offset, length[, position], callback )
fs.write(fd, data[, position[, encoding]], callback )
要使用非同步寫入檔案,先需要通過 open() 開啟檔案,然後在回
調函式中通過 write() 寫入。
引數:
– fd 檔案描述符
– data 要寫入的資料( String 或 Buffer )
– offset buffer 寫入的偏移量
– length 寫入的長度
– position 寫入的起始位置
– encoding 寫入編碼

流式檔案寫入

往一個檔案中寫入大量資料時,最好的方法之一
是使用流。
若要將資料非同步傳送到檔案,首需要使用以下語
法建立一個 Writable 物件:
– fs.createWriteStream(path[, options ])
path 檔案路徑
options {encoding:"",mode:"",flag:""}
一旦你打開了 Writable 檔案流,就可以使用
write() 方法來寫入它,寫入完成後,在呼叫 end()
方法來關閉流。

讀取檔案

fs 中提供了四 種讀取檔案的方式
– 簡單檔案讀取
– 同步檔案讀取
– 非同步檔案讀取
– 流式檔案讀取

簡單檔案 讀取

fs.readFile(file[, options], callback )
fs.readFileSync(file[, options ])
– 引數:
file 檔案路徑或檔案描述符
options|
– encoding|預設 = null
– flag預設 = 'r '
callback 回撥函式,有兩個引數 err 、 data

同步檔案讀取

fs.readSync(fd, buffer, offset, length,
position )
– 引數:
fd 檔案描述符
buffer 讀取檔案的緩衝區
offset buffer 的開始寫入的位置
length 要讀取的位元組數
position 開始讀取檔案的位置

非同步 檔案讀取

fs.read(fd, buffer, offset, length,
position, callback )
– 引數:
fd 檔案描述符
buffer 讀取檔案的 緩衝區
offset buffer 的開始寫入的位置
length 要讀取的位元組數
position 開始讀取檔案的 位置
callback 回撥函式 引數 err , bytesRead , buffer

流式檔案讀取

從一個檔案中讀取大量的資料時,最好的方法之一就是
流式讀取,這樣將把一個檔案作為 Readable 流的形式
開啟。
要從非同步從檔案傳輸資料,首先需要通過以下語法建立
一個 Readable 流物件:
– fs.createReadStream(path[, options ])
path 檔案路徑
options {encoding:"",mode:"",flag :""}
當你開啟 Readable 檔案流以後,可以通過 readable 事
件和 read() 請求,或通過 data 事件處理程式輕鬆地從它
讀出。

其他操作

驗證路徑是否存在
– fs.exists(path , callback)
– fs.existsSync(path )
獲取檔案資訊
– fs.stat(path, callback )
– fs.statSync(path )
刪除檔案
– fs.unlink(path, callback )
– fs.unlinkSync(path )

其他操作

列出檔案
– fs.readdir(path [, options], callback )
– fs.readdirSync(path[, options ])
截斷檔案
– fs.truncate(path, len, callback )
– fs.truncateSync(path, len )
建立目錄
– fs.mkdir(path[, mode], callback )
– fs.mkdirSync(path[, mode])

其他操作

刪除目錄
– fs.rmdir(path, callback )
– fs.rmdirSync(path)
重新命名檔案和目錄
– fs.rename(oldPath, newPath, callback )
– fs.renameSync(oldPath, newPath )
監視檔案更改寫入
– fs.watchFile(filename[, options], listener)