node.js單進程,單線程的程序 每個api都支持回調 全部的事件機制都是設計模式中的html
一共是23種設計模式 http://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/observer.html 一個對象發生改變的時候,將自動通知其餘對象,其餘對象將相應的作出反應。發生改變的對象爲觀察目標,被通知的對象爲觀察者。一個觀察目標能夠對應多個觀察者,而這些觀察者之間沒有任何聯繫,能夠根據須要增長觀察者,使得系統更加容易擴展,依賴關係爲一對多,又被稱爲模型-視圖模式node
web server接收到請求,將其關閉,進行處理,而後接着服務下一個web請求。 當請求完成之後,放回處理隊列,當到達隊列開頭的時候,將其結果返回給用戶 即非阻塞式I/O 事件驅動I/O 會有一個主循環來監聽事件,當檢測到事件之後,觸發回調函數es6
PS C:\Users\mingm\Desktop\test> node main.js
鏈接成功
數據接收成功
程序執行完畢
PS C:\Users\mingm\Desktop\test>
複製代碼
// 引入一個 events 模塊
var events = require('events');
// 建立 eventEmitter對象
var eventEmitter = new events.EventEmitter();
// 建立connection事件的處理程序
var connectHandLer = function connected() {
console.log('鏈接成功');
// 觸發 data_received 事件
eventEmitter.emit('data_received');
};
// 綁定cinnection事件處理程序
eventEmitter.on('connection', connectHandLer);
// 綁定data_received事件,並完成處理程序的書寫
eventEmitter.on(
'data_received',
function() {
console.log('數據接收成功');
}
);
// 觸發 connection 事件
eventEmitter.emit('connection');
console.log('程序執行完畢');
複製代碼
程序的執行過程,先完成各類綁定,觸發connection事件之後,尋找綁定的處理程序,爲connected(),而後,執行一半,又被觸發,data_received事件。尋找綁定的處理程序。一個匿名函數,執行,事件所有完成,執行最後一句,程序執行完畢。 多用戶執行的狀況下,觸發事件之後,若處理程序正被其餘用戶佔用,排隊,直到前方所有處理完成之後,接着該用戶使用處理程序進行處理。web
node全部的異步I/O操做在完成的時候都會發送到一個事件到達事件隊列。node裏的對象可以分發事件 產生的事件的對象都是events.EventEmitter的實例json
events模塊提供一個對象,它是對事件的觸發和事件的監聽的封裝設計模式
PS C:\Users\mingm\Desktop\test> node main.js
事件觸發
PS C:\Users\mingm\Desktop\test>
複製代碼
過五秒後響應api
// event.js文件
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter(); // 建立一個event對象
event.on('some_event', function(){console.log('事件觸發');});
setTimeout(function(){event.emit('some_event');}, 5000);
複製代碼
大概解釋一下這段代碼 前兩句很簡單,後兩句說一下,event的對象註冊了一個事件的監聽器。這個事件的監聽器爲一個匿名函數,事件名稱爲some_event,當5000秒之後被觸發先對象event發送一個事件some_event觸發了匿名函數即監聽器,監聽器被執行。 其中EventEmitter的每一個事件由一個事件名和若干參數組成,對於一個事件能有若干的監聽器,當事件觸發的時候,監聽器會被依次調用,事件參數做爲回調函數的參數進行傳遞,須要注意的是,監聽器會被依次調用數組
error是一個單獨列出來的事件,通常要爲其綁定一個監聽器,由於node若是拋出error,若沒有監聽器執行,將會直接退出執行,並返回錯誤緩存
處理TCP或者文件流的時候,須要用到二進制的數據,定義了一個Buffer類,該類用於專門存放二進制數據的緩衝區bash
const buf = Buffer.from('ming', 'ascii'); // 聲明一個只讀的變量
console.log(buf.toString('hex'));
console.log(buf.toString('utf-8'));
複製代碼
PS C:\Users\mingm\Desktop\test> node main.js
6d696e67
ming
PS C:\Users\mingm\Desktop\test>
複製代碼
PS C:\Users\mingm\Desktop\test> node main.js
23456789:;<=>?@ABCDEFGHIJK
23456789:;<=>?@ABCDEFGHIJK
PS C:\Users\mingm\Desktop\test>
複製代碼
buf = Buffer.alloc(26);
for(var i = 0; i < 26; i++){
buf[i] = 50 + i;
};
console.log(buf.toString('ascii'));
console.log(buf.toString('utf8'));
複製代碼
PS C:\Users\mingm\Desktop\test> node main.js
{"type":"Buffer","data":[1,2,3,4,5]}
PS C:\Users\mingm\Desktop\test>
複製代碼
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);
console.log(json);
複製代碼
> JSON.parse('{"1": 3, "2": [4, 5, 6]}', function (k, v) {
... console.log(k); // 輸出當前的屬性名,從而得知遍歷順序是從內向外的,
... console.log("----------"); // 最後一個屬性名會是個空字符串。
... console.log(v);
... });
1
----------
3
0
----------
4
1
----------
5
2
----------
6
2
----------
[ <3 empty items> ]
----------
{}
undefined
>
複製代碼
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);
console.log(json);
const copy = JSON.parse( // 調用JSON.parse函數,將字符串轉換爲對象,後一個參數爲轉換的函數,轉換的時候將會調用
json,
(key, value) => { // 此爲es6的語法,一個匿名函數
console.log(value, '----', !!value, '----', value.type, '-----', value.data);
return value && value.type === 'Buffer' ? Buffer.from(value.data): value; // 只留下最後一個進行轉換,前面的轉換所有被覆蓋
}
)
// 輸出: <Buffer 01 02 03 04 05>
console.log(copy);
複製代碼
PS C:\Users\mingm\Desktop\test> node main.js
{"type":"Buffer","data":[1,2,3,4,5]}
Buffer ---- true ---- undefined ----- undefined
1 '----' true '----' undefined '-----' undefined
2 '----' true '----' undefined '-----' undefined
3 '----' true '----' undefined '-----' undefined
4 '----' true '----' undefined '-----' undefined
5 '----' true '----' undefined '-----' undefined
[ 1, 2, 3, 4, 5 ] '----' true '----' undefined '-----' undefined
{ type: 'Buffer', data: [ 1, 2, 3, 4, 5 ] } '----' true '----' 'Buffer' '-----' [ 1, 2, 3, 4, 5 ]
<Buffer 01 02 03 04 05>
PS C:\Users\mingm\Desktop\test>
複製代碼
var buffer1 = Buffer.from('222');
var buffer2 = Buffer.from('3333');
var buffer3 = Buffer.concat([buffer1, buffer2]);
console.log(buffer3.toString());
複製代碼
流爲一個抽象的接口,
PS C:\Users\mingm\Desktop\test> node main.js
end!
33333333333333333333333333
PS C:\Users\mingm\Desktop\test>
複製代碼
var fs = require('fs');
var data = '';
// 建立可讀流
var readerStream = fs.createReadStream('input.txt');
// 設置編碼爲 utf8
readerStream.setEncoding('UTF8');
// 處理流事件 data事件
readerStream.on('data', (chunk) => {data += chunk;}); // 遇到數據讀取,將讀取到的內容賦值給data
// 處理流事件 end事件
readerStream.on('end', () => {console.log(data);}); // 將讀取到的保存到內存中的數據打印出來
// 處理事件 error
readerStream.on('error', (err) => {console.log(err.stack);}); // 處理error事件,將錯誤輸出,避免程序的運行中斷
console.log('end!');
複製代碼
PS C:\Users\mingm\Desktop\test> node main.js
程序執行完畢
寫入完成
PS C:\Users\mingm\Desktop\test>
複製代碼
var fs = require('fs');
var data = '這是一段示例';
// 建立一個能夠寫入的流,寫入到文件output.txt中
var writerStream = fs.createWriteStream('output.txt');
// 使用 utf8 編碼寫入數據
writerStream.write(data, 'UTF8');
// 標記文件末尾
writerStream.end();
// 處理流事件 --> data, end, add error
writerStream.on('finish', () => {console.log('寫入完成');});
writerStream.on('error', () => {console.log(err.stack);});
console.log('程序執行完畢');
複製代碼
把兩個文件之間創建流,讓一個文件的數據流向另一個文件
PS C:\Users\mingm\Desktop\test> node main.js
程序執行完畢
PS C:\Users\mingm\Desktop\test>
複製代碼
var fs = require('fs');
// 建立一個可讀流
var readerStream = fs.createReadStream('input.txt');
// 建立一個可寫流
var writerStream = fs.createWriteStream('output.txt');
// 管道讀寫操做
// 將兩個流經過管道鏈接起來
readerStream.pipe(writerStream);
console.log('程序執行完畢');
複製代碼
這裏須要注意的是,因爲流的影響,致使在操做的時候,會覆蓋掉要寫入文件的內容,原先的內容會被覆蓋
PS C:\Users\mingm\Desktop\test> node main.js
文件壓縮完成
PS C:\Users\mingm\Desktop\test>
複製代碼
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('文件壓縮完成');
複製代碼
var fs = require('fs');
var read = fs.createReadStream('output.txt');
var write = fs.createWriteStream('input.txt');
read.pipe(write);
console.log('執行完畢');
複製代碼
具體詳細,請查文檔 https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_options https://nodejs.org/api/fs.html#fs_file_system_flags 文檔寫的很詳細,後面的參數爲一個對象,經過對象便可進行修改
模塊以前已經闡述過一部分,這裏闡述服務器端的模塊
node中自帶了一個http模塊,在代碼中請求他,並將返回值賦值給本地變量。即本地變量變成了一個擁有全部http模塊所提供的公共方法的對象。 node中有四個模塊,(原生模塊和三種文件模塊)
原生模塊和文件模塊優先級不一樣,都會優先從文件模塊的緩存中加載以及存在的模塊
原生模塊的優先級低於文件模塊緩存的優先級。原生模塊也有緩存區
這個上一篇以及闡述完成,不在闡述