Node.js從入門到實戰(二)Node.js基本用法
參考:
一、Node.js中的模組
Node.js使用require引入依賴的模組,因此模組是Node.js中的重要組成部分,這篇部落格主要羅列一下常用的Node.js模組,並且在後期會新增在工作中用到的模組參考備用。
二、Node.js EventEmitter
Node.js 所有的非同步 I/O 操作在完成時都會發送一個事件到事件佇列。Node.js裡面的許多物件都會分發事件,所有這些產生事件的物件都是 events.EventEmitter 的例項。
events 模組只提供了一個物件: events.EventEmitter。EventEmitter 的核心就是事件觸發與事件監聽器功能的封裝。你可以通過require("events");來訪問該模組。
// 引入 events 模組
var events = require('events');
// 建立 eventEmitter 物件
var eventEmitter = new events.EventEmitter();
EventEmitter 的每個事件由一個事件名和若干個引數組成,事件名是一個字串,通常表達一定的語義。對於每個事件,EventEmitter 支援 若干個事件監聽器。當事件觸發時,註冊到這個事件的事件監聽器被依次呼叫,事件引數作為回撥函式引數傳遞。emitter 為事件 someEvent 註冊了兩個事件監聽器,然後觸發了 someEvent 事件。執行結果中可以看到兩個事件監聽器回撥函式被先後呼叫。 這就是EventEmitter最簡單的用法。EventEmitter 提供了多個屬性,如 on 和 emit。on 函式用於繫結事件函式,emit 屬性用於觸發一個事件。接下來我們來具體看下 EventEmitter 的屬性介紹。//event.js 檔案 var events = require('events'); var emitter = new events.EventEmitter(); emitter.on('someEvent', function(arg1, arg2) { console.log('listener1', arg1, arg2); }); emitter.on('someEvent', function(arg1, arg2) { console.log('listener2', arg1, arg2); }); emitter.emit('someEvent', 'arg1 引數', 'arg2 引數');
序號 | 方法 & 描述 |
---|---|
1 |
addListener(event, listener) 為指定事件新增一個監聽器到監聽器陣列的尾部。 |
2 |
on(event, listener) 為指定事件註冊一個監聽器,接受一個字串 event 和一個回撥函式。 server |
3 |
once(event, listener) 為指定事件註冊一個單次監聽器,即 監聽器最多隻會觸發一次,觸發後立刻解除該監聽器。 server.once('connection',function(stream){ console.log('Ah, we have our first user!');}); |
4 |
removeListener(event, listener) 移除指定事件的某個監聽器,監聽器必須是該事件已經註冊過的監聽器。 它接受兩個引數,第一個是事件名稱,第二個是回撥函式名稱。 var callback =function(stream){ console.log('someone connected!');}; server.on('connection', callback);// ... server.removeListener('connection', callback); |
5 |
removeAllListeners([event]) 移除所有事件的所有監聽器, 如果指定事件,則移除指定事件的所有監聽器。 |
6 |
setMaxListeners(n) 預設情況下, EventEmitters 如果你新增的監聽器超過 10 個就會輸出警告資訊。 setMaxListeners 函式用於提高監聽器的預設限制的數量。 |
7 |
listeners(event) 返回指定事件的監聽器陣列。 |
8 |
emit(event, [arg1], [arg2], [...]) 按引數的順序執行每個監聽器,如果事件有註冊監聽返回 true,否則返回 false。 |
類方法
序號 | 方法 & 描述 |
---|---|
1 |
listenerCount(emitter, event) 返回指定事件的監聽器數量。 |
事件
序號 | 事件 & 描述 |
---|---|
1 |
newListener
該事件在新增新監聽器時被觸發。 |
2 |
removeListener
從指定監聽器陣列中刪除一個監聽器。需要注意的是,此操作將會改變處於被刪監聽器之後的那些監聽器的索引。 |
var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error');
執行時會顯示以下錯誤:
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Uncaught, unspecified 'error' event.
at EventEmitter.emit (events.js:50:15)
at Object.<anonymous> (/home/byvoid/error.js:5:9)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback (node.js:192:40)
三、Node.js Buffer
JavaScript 語言自身只有字串資料型別,沒有二進位制資料型別。但在處理像TCP流或檔案流時,必須使用到二進位制資料。因此在 Node.js中,定義了一個 Buffer 類,該類用來建立一個專門存放二進位制資料的快取區。在 Node.js 中,Buffer 類是隨 Node 核心一起釋出的核心庫。Buffer 庫為 Node.js 帶來了一種儲存原始資料的方法,可以讓 Node.js 處理二進位制資料,每當需要在
Node.js 中處理I/O操作中移動的資料時,就有可能使用 Buffer 庫。原始資料儲存在 Buffer 類的例項中。一個 Buffer 類似於一個整數陣列,但它對應於 V8 堆記憶體之外的一塊原始記憶體。
Buffer 例項一般用於表示編碼字元的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六進位制編碼的資料。 通過使用顯式的字元編碼,就可以在 Buffer 例項與普通的 JavaScript 字串之間進行相互轉換。Node.js 目前支援的字元編碼包括:
- ascii - 僅支援 7 位 ASCII 資料。如果設定去掉高位的話,這種編碼是非常快的。
- utf8 - 多位元組編碼的 Unicode 字元。許多網頁和其他文件格式都使用 UTF-8 。
- utf16le - 2 或 4 個位元組,小位元組序編碼的 Unicode 字元。支援代理對(U+10000 至 U+10FFFF)。
- ucs2 - utf16le 的別名。
- base64 - Base64 編碼。
- latin1 - 一種把 Buffer 編碼成一位元組編碼的字串的方式。
- binary - latin1 的別名。
- hex - 將每個位元組編碼為兩個十六進位制字元。
Buffer類中的方法如下:
序號 | 方法 & 描述 |
---|---|
1 |
new Buffer(size) 分配一個新的 size 大小單位為8位位元組的 buffer。 注意, size 必須小於 kMaxLength,否則,將會丟擲異常 RangeError。廢棄的: 使用 Buffer.alloc() 代替(或 Buffer.allocUnsafe())。 |
2 |
new Buffer(buffer) 拷貝引數 buffer 的資料到 Buffer 例項。廢棄的: 使用 Buffer.from(buffer) 代替。 |
3 |
new Buffer(str[, encoding]) 分配一個新的 buffer ,其中包含著傳入的 str 字串。 encoding 編碼方式預設為 'utf8'。 廢棄的: 使用 Buffer.from(string[, encoding]) 代替。 |
4 |
buf.length 返回這個 buffer 的 bytes 數。注意這未必是 buffer 裡面內容的大小。length 是 buffer 物件所分配的記憶體數,它不會隨著這個 buffer 物件內容的改變而改變。 |
5 |
buf.write(string[, offset[, length]][, encoding]) 根據引數 offset 偏移量和指定的 encoding 編碼方式,將引數 string 資料寫入buffer。 offset 偏移量預設值是 0, encoding 編碼方式預設是 utf8。 length 長度是將要寫入的字串的 bytes 大小。 返回 number 型別,表示寫入了多少 8 位位元組流。如果 buffer 沒有足夠的空間來放整個 string,它將只會只寫入部分字串。 length 預設是 buffer.length - offset。 這個方法不會出現寫入部分字元。 |
6 |
buf.writeUIntLE(value, offset, byteLength[, noAssert]) 將 value 寫入到 buffer 裡, 它由 offset 和 byteLength 決定,最高支援 48 位無符號整數,小端對齊,例如: const buf =Buffer.allocUnsafe(6); buf.writeUIntLE(0x1234567890ab,0,6);// 輸出: <Buffer ab 90 78 56 34 12> console.log(buf);noAssert 值為 true 時,不再驗證 value 和 offset 的有效性。 預設是 false。 |
7 |
buf.writeUIntBE(value, offset, byteLength[, noAssert]) 將 value 寫入到 buffer 裡, 它由 offset 和 byteLength 決定,最高支援 48 位無符號整數,大端對齊。noAssert 值為 true 時,不再驗證 value 和 offset 的有效性。 預設是 false。 const buf =Buffer.allocUnsafe(6); buf.writeUIntBE(0x1234567890ab,0,6);// 輸出: <Buffer 12 34 56 78 90 ab> console.log(buf); |
8 |
buf.writeIntLE(value, offset, byteLength[, noAssert]) 將value 寫入到 buffer 裡, 它由offset 和 byteLength 決定,最高支援48位有符號整數,小端對齊。noAssert 值為 true 時,不再驗證 value 和 offset 的有效性。 預設是 false。 |
9 |
buf.writeIntBE(value, offset, byteLength[, noAssert]) 將value 寫入到 buffer 裡, 它由offset 和 byteLength 決定,最高支援48位有符號整數,大端對齊。noAssert 值為 true 時,不再驗證 value 和 offset 的有效性。 預設是 false。 |
10 |
buf.readUIntLE(offset, byteLength[, noAssert]) 支援讀取 48 位以下的無符號數字,小端對齊。noAssert 值為 true 時, offset 不再驗證是否超過 buffer 的長度,預設為 false。 |
11 |
buf.readUIntBE(offset, byteLength[, noAssert]) 支援讀取 48 位以下的無符號數字,大端對齊。noAssert 值為 true 時, offset 不再驗證是否超過 buffer 的長度,預設為 false。 |
12 |
buf.readIntLE(offset, byteLength[, noAssert]) 支援讀取 48 位以下的有符號數字,小端對齊。noAssert 值為 true 時, offset 不再驗證是否超過 buffer 的長度,預設為 false。 |
13 |
buf.readIntBE(offset, byteLength[, noAssert]) 支援讀取 48 位以下的有符號數字,大端對齊。noAssert 值為 true 時, offset 不再驗證是否超過 buffer 的長度,預設為 false。 |
14 |
buf.toString([encoding[, start[, end]]]) 根據 encoding 引數(預設是 'utf8')返回一個解碼過的 string 型別。還會根據傳入的引數 start (預設是 0) 和 end (預設是 buffer.length)作為取值範圍。 |
15 |
buf.toJSON() 將 Buffer 例項轉換為 JSON 物件。 |
16 |
buf[index] 獲取或設定指定的位元組。返回值代表一個位元組,所以返回值的合法範圍是十六進位制0x00到0xFF 或者十進位制0至 255。 |
17 |
buf.equals(otherBuffer) 比較兩個緩衝區是否相等,如果是返回 true,否則返回 false。 |
18 |
buf.compare(otherBuffer) 比較兩個 Buffer 物件,返回一個數字,表示 buf 在 otherBuffer 之前,之後或相同。 |
19 |
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]]) buffer 拷貝,源和目標可以相同。 targetStart 目標開始偏移和 sourceStart 源開始偏移預設都是 0。 sourceEnd 源結束位置偏移預設是源的長度 buffer.length 。 |
20 |
buf.slice([start[, end]]) 剪下 Buffer 物件,根據 start(預設是 0 ) 和 end (預設是 buffer.length ) 偏移和裁剪了索引。 負的索引是從 buffer 尾部開始計算的。 |
21 |
buf.readUInt8(offset[, noAssert]) 根據指定的偏移量,讀取一個無符號 8 位整數。若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 如果這樣 offset 可能會超出buffer 的末尾。預設是 false。 |
22 |
buf.readUInt16LE(offset[, noAssert]) 根據指定的偏移量,使用特殊的 endian 位元組序格式讀取一個無符號 16 位整數。若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出 buffer 的末尾。預設是 false。 |
23 |
buf.readUInt16BE(offset[, noAssert]) 根據指定的偏移量,使用特殊的 endian 位元組序格式讀取一個無符號 16 位整數,大端對齊。若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出 buffer 的末尾。預設是 false。 |
24 |
buf.readUInt32LE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 位元組序格式讀取一個無符號 32 位整數,小端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出buffer 的末尾。預設是 false。 |
25 |
buf.readUInt32BE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 位元組序格式讀取一個無符號 32 位整數,大端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出buffer 的末尾。預設是 false。 |
26 |
buf.readInt8(offset[, noAssert]) 根據指定的偏移量,讀取一個有符號 8 位整數。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出 buffer 的末尾。預設是 false。 |
27 |
buf.readInt16LE(offset[, noAssert]) 根據指定的偏移量,使用特殊的 endian 格式讀取一個 有符號 16 位整數,小端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出 buffer 的末尾。預設是 false。 |
28 |
buf.readInt16BE(offset[, noAssert]) 根據指定的偏移量,使用特殊的 endian 格式讀取一個 有符號 16 位整數,大端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出 buffer 的末尾。預設是 false。 |
29 |
buf.readInt32LE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 位元組序格式讀取一個有符號 32 位整數,小端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出buffer 的末尾。預設是 false。 |
30 |
buf.readInt32BE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 位元組序格式讀取一個有符號 32 位整數,大端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出buffer 的末尾。預設是 false。 |
31 |
buf.readFloatLE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 位元組序格式讀取一個 32 位雙浮點數,小端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出buffer的末尾。預設是 false。 |
32 |
buf.readFloatBE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 位元組序格式讀取一個 32 位雙浮點數,大端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出buffer的末尾。預設是 false。 |
33 |
buf.readDoubleLE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian位元組序格式讀取一個 64 位雙精度數,小端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出buffer 的末尾。預設是 false。 |
34 |
buf.readDoubleBE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian位元組序格式讀取一個 64 位雙精度數,大端對齊。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 offset 可能會超出buffer 的末尾。預設是 false。 |
35 |
buf.writeUInt8(value, offset[, noAssert]) 根據傳入的 offset 偏移量將 value 寫入 buffer。注意:value 必須是一個合法的無符號 8 位整數。 若引數 noAssert 為 true 將不會驗證 offset 偏移量引數。 這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則不要使用。預設是 false。 |
36 |
buf.writeUInt16LE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的無符號 16 位整數,小端對齊。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value 可能過大,或者 offset 可能會超出buffer的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
37 |
buf.writeUInt16BE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的無符號 16 位整數,大端對齊。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value 可能過大,或者 offset 可能會超出buffer的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
38 |
buf.writeUInt32LE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式(LITTLE-ENDIAN:小位元組序)將 value 寫入buffer。注意:value 必須是一個合法的無符號 32 位整數,小端對齊。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著value 可能過大,或者offset可能會超出buffer的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
39 |
buf.writeUInt32BE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式(Big-Endian:大位元組序)將 value 寫入buffer。注意:value 必須是一個合法的有符號 32 位整數。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value 可能過大,或者offset可能會超出buffer的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
40 | buf.writeInt8(value, offset[, noAssert])<br根據傳入的 offset="" 偏移量將="" value="" 寫入="" buffer="" 。注意:value="" 必須是一個合法的="" signed="" 8="" 位整數。="" 若引數="" noassert="" 為="" true="" 將不會驗證="" 和="" 偏移量引數。="" 這意味著="" 可能過大,或者="" 可能會超出="" 的末尾從而造成="" 被丟棄。="" 除非你對這個引數非常有把握,否則儘量不要使用。預設是="" false。<="" td=""> |
41 |
buf.writeInt16LE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的 signed 16 位整數。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false 。 |
42 |
buf.writeInt16BE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的 signed 16 位整數。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false 。 |
43 |
buf.writeInt32LE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的 signed 32 位整數。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
44 |
buf.writeInt32BE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的 signed 32 位整數。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
45 |
buf.writeFloatLE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer 。注意:當 value 不是一個 32 位浮點數型別的值時,結果將是不確定的。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
46 |
buf.writeFloatBE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer 。注意:當 value 不是一個 32 位浮點數型別的值時,結果將是不確定的。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
47 |
buf.writeDoubleLE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個有效的 64 位double 型別的值。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成value被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
48 |
buf.writeDoubleBE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個有效的 64 位double 型別的值。 若引數 noAssert 為 true 將不會驗證 value 和 offset 偏移量引數。 這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成value被丟棄。 除非你對這個引數非常有把握,否則儘量不要使用。預設是 false。 |
49 |
buf.fill(value[, offset][, end]) 使用指定的 value 來填充這個 buffer。如果沒有指定 offset (預設是 0) 並且 end (預設是 buffer.length) ,將會填充整個buffer。 |
四、Node.js Stream
Stream 是一個抽象介面,Node 中有很多物件實現了這個介面。例如,對http 伺服器發起請求的request 物件就是一個 Stream,還有stdout(標準輸出)。Node.js,Stream 有四種流型別:
- Readable - 可讀操作。
- Writable - 可寫操作。
- Duplex - 可讀可寫操作.
- Transform - 操作被寫入資料,然後讀出結果。
- data - 當有資料可讀時觸發。
- end - 沒有更多的資料可讀時觸發。
- error - 在接收和寫入過程中發生錯誤時觸發。
- finish - 所有資料已被寫入到底層系統時觸發。
如下程式碼展示了Stream ReadStream的用法:
var fs = require("fs");
var data = '';
// 建立可讀流
var readerStream = fs.createReadStream('input.txt');
// 設定編碼為 utf8。
readerStream.setEncoding('UTF8');
// 處理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
data += chunk;
});
readerStream.on('end',function(){
console.log(data);
});
readerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程式執行完畢");
如下程式碼顯示了Stream WriteStream的用法:
var fs = require("fs");
var data = '菜鳥教程官網地址:www.runoob.com';
// 建立一個可以寫入的流,寫入到檔案 output.txt 中
var writerStream = fs.createWriteStream('output.txt');
// 使用 utf8 編碼寫入資料
writerStream.write(data,'UTF8');
// 標記檔案末尾
writerStream.end();
// 處理流事件 --> data, end, and error
writerStream.on('finish', function() {
console.log("寫入完成。");
});
writerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程式執行完畢");
Stream具備管道流和鏈式流兩種用法:
管道流:
var fs = require("fs");
// 建立一個可讀流
var readerStream = fs.createReadStream('input.txt');
// 建立一個可寫流
var writerStream = fs.createWriteStream('output.txt');
// 管道讀寫操作
// 讀取 input.txt 檔案內容,並將內容寫入到 output.txt 檔案中
readerStream.pipe(writerStream);
console.log("程式執行完畢");
管道流可以處理讀寫操作。
鏈式流:
鏈式是通過連線輸出流到另外一個流並建立多個流操作鏈的機制。鏈式流一般用於管道操作。
接下來我們就是用管道和鏈式來壓縮和解壓檔案。建立 compress.js 檔案, 程式碼如下:
var fs = require("fs");
var zlib = require('zlib');
// 壓縮 input.txt 檔案為 input.txt.gz
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz'));
console.log("檔案壓縮完成。");
五、Node.js路由
Node.js路由中對HTTP請求的URL的解析需要依賴以下url 和querystring 模組:
url.parse(string).query
|
url.parse(string).pathname |
| |
| |
------ -------------------
http://localhost:8888/start?foo=bar&hello=world
--- -----
| |
| |
querystring.parse(queryString)["foo"] |
|
querystring.parse(queryString)["hello"]
現在我們來給 onRequest() 函式加上一些邏輯,用來找出瀏覽器請求的 URL 路徑,server.js檔案的內容如下:var http = require("http");
var url = require("url");
function start() {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
此時的server並無區分pathname對映的能力,如下新增router.js用於處理來自不同路徑的請求:
function route(pathname) {
console.log("About to route a request for " + pathname);
}
exports.route = route;
首先,我們來擴充套件一下伺服器的 start() 函式,以便將路由函式作為引數傳遞過去:
var http = require("http");
var url = require("url");
function start(route) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(pathname);
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
同時,我們會相應擴充套件 index.js,使得路由函式可以被注入到伺服器中:
var server = require("./server");
var router = require("./router");
server.start(router.route);
此時請求localhost:8888時即經過了router的處理。
五、Node.js 全域性變數
JavaScript 中有一個特殊的物件,稱為全域性物件(Global Object),它及其所有屬性都可以在程式的任何地方訪問,即全域性變數。
在瀏覽器 JavaScript 中,通常 window 是全域性物件, 而 Node.js 中的全域性物件是 global,所有全域性變數(除了 global 本身以外)都是 global 物件的屬性。在 Node.js 我們可以直接訪問到 global 的屬性,而不需要在應用中包含它。
global 最根本的作用是作為全域性變數的宿主。按照 ECMAScript 的定義,滿足以下條 件的變數是全域性變數:
- 在最外層定義的變數;
- 全域性物件的屬性;
- 隱式定義的變數(未定義直接賦值的變數)。
注意: 永遠使用 var 定義變數以避免引入全域性變數,因為全域性變數會汙染 名稱空間,提高程式碼的耦合風險。
Node.js中常用的全域性變數有:
- __filename __filename 表示當前正在執行的指令碼的檔名。它將輸出檔案所在位置的絕對路徑,且和命令列引數所指定的檔名不一定相同。 如果在模組中,返回的值是模組檔案的路徑。
- __dirname __dirname 表示當前執行指令碼所在的目錄。
- setTimeout(cb, ms) setTimeout(cb, ms) 全域性函式在指定的毫秒(ms)數後執行指定函式(cb)。:setTimeout() 只執行一次指定函式。
- 返回一個代表定時器的控制代碼值。
- clearTimeout(t) clearTimeout( t ) 全域性函式用於停止一個之前通過 setTimeout() 建立的定時器。 引數 t 是通過 setTimeout() 函式建立的定時器。
- setInterval(cb, ms) setInterval(cb, ms) 全域性函式在指定的毫秒(ms)數後執行指定函式(cb)。返回一個代表定時器的控制代碼值。可以使用 clearInterval(t) 函式來清除定時器。setInterval() 方法會不停地呼叫函式,直到 clearInterval() 被呼叫或視窗被關閉。
- console console 用於提供控制檯標準輸出,它是由 Internet Explorer 的 JScript 引擎提供的除錯工具,後來逐漸成為瀏覽器的實施標準。Node.js 沿用了這個標準,提供與習慣行為一致的 console 物件,用於