nodejs的基礎概念
1.node 安裝與相關配置。
2.Node.jsREPL(交互式解釋器)
類似於控制臺,可以輸入命令,並接受系統的響應。
REPL 的功能:
1.讀取:讀取用戶輸入,解析輸入的 js 數據結構,並存儲在內存中。
2.執行:執行輸入的數據結構。
3.打印:輸出結果。
4.循環:可以循環1、2、3操作指導ctrl+c兩次退出。
開啟 Node 終端:node 即可開啟。
運算符:+、-、*、/,還支持括號改變優先級。
變量定義:使用var來定義變量。常用的輸出 API:console.log()。
多行表達式:這裏指的是循環,與在 js 中做的循環是一致的。每輸出一行回車就可以,node 會自動檢測是否為連續多行表達式。
下劃線_變量:可以使用下劃線變量來獲取上一個表達式的運算結果。
REPL 命令:
Ctrl+c 退出當前終端。
Ctrl+c 連續兩次,退出Node REPL
Ctrl+d 退出 Node REPL
向上/向下鍵-查看輸入的歷史命令。
tab 鍵 列出當前命令
.help 列出使用命令
.break 退出多行表達式
.clear 退出多行表達式
.save filename 保存當前的 Node REPL 會話到指定文件。
.load filename 載入當前 Node REPL 會話的文件內容。
3. Node.js 回調函數
Node.js異步編程的直接體現就是回調。
異步編程依托於回調來實現,但是不能說使用回調就是異步化。
回調函數在完成任務後就會調用,Node使用了大量的回調函數,Node所有的API都支持回調函數。
註:阻塞是按順序執行的,而非阻塞是不需要按順序的,所以如果需要處理回調函數的參數,我們需要寫在回調函數內。
4.Node.js事件循環
Node.js是單進程單線程應用,但是通過事件和回調支持並發, 所以性能很高。
Node.js的每一個API都是異步的(這裏個人認為表達的意思應該是每一個API都是支持回調。參考第三部分),並作為一個獨立線程運行,使用異步函數調用,並處理並發。
Node.js基本上所有的事件機制都是用設計模式中的觀察者模式實現的。
Node.js單線程類似進入一個while(true)的事件循環,直到沒有事件,觀察者退出,每個異步事件都生成一個事件觀察者。如果有事件發生就調用該回調函數。
Node.js中內置多個事件,可以引入events模塊,並通過實例化EventEmitter類來綁定和監聽事件。
在Node中:執行異步操作的函數將回調函數作為最後一個參數,回調函數接受錯誤對象作為第一個參數。
5.Node.js EventEmitter
Node.js 所有的異步I/O操作在完成時都會發送一個事件到事件隊列。
Node.js裏面的許多對象都會分發事件:一個net.Server對象會在每次有新連接時分發一個事件,一個fs.readStream對象會在文件被打開的時候發出一個事件。所有產生的事件的對象都是events.EventEmitter的實例。
EventEmitter類
events模塊只提供了一個對象,events.EventEmitter。EventEmitter的核心就是事件觸發與事件監聽器功能的封裝。
// 引入 events 模塊 var events = require(‘events‘); // 創建 eventEmitter 對象 var eventEmitter = new events.EventEmitter();
EventEmitter對象如果再實例化時發生錯誤,就會觸發error事件。當添加新的監聽器時,newListener事件會觸發,當監聽器被移除時,removeListener事件被觸發。
簡例說明EventEmitter用法:
//event.js文件 var EventEmitter = require(‘events‘).EventEmitter; var event = new EventEmitter(); event.on(‘some_evnet‘, function() { console.log(‘some_event 事件觸發‘); }); setTimeOut(function() { event.emit(‘some_event‘); }, 1000);
EventEmitter的每個事件由一個事件名和若幹個參數組成,事件名是一個字符串,通常表達一定的含義,對於每個事件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參數‘);
執行結果:
在上述例子中,emitter為事件註冊了兩個監聽器,然後觸發了事件。這是最簡單的EventEmitter的用法。
EventEmitter提供了多個屬性,如on用於事件綁定,emit用於觸發一個事件。
具體的API
error事件
EventEmitter定義了一個特殊的事件error,它包含了錯誤的語義,我們在遇到異常時,通常會觸發error事件。
當error被觸發時,EventEmitter規定如果沒有響應的監聽器,Node.js會把它當做異常,退出程序並輸出錯誤信息。
我們一般要為會觸發error事件的對象設置監聽器,避免出現錯誤後整個程序崩潰。
關於EventEmitter,
我們大多時候只會在對象中繼承它,包括fs、net、http在內的。只要是支持事件響應的核心模塊都是EventEmitter的子類。原因有二:
1.具有某個實體功能的對象實現事件符合語義,事件的監聽和發生應該是一個對象的方法。
2.js的對象機制是基於原型的,支持部分多繼承,繼承EventEmitter不會打亂對象原有的繼承關系。
註:補充:實踐隊列中出現一個未綁定事件會觸發error事件,若未綁定error事件則程序拋出異常結束。
6.Node.js Buffer(緩沖區)
js只有字符串數據類型,沒有二進制數據類型。但是在處理流時,必須使用二進制數據,因此在Node.js中定義了Buffer類,該類用來創建一個專門存放二進制數據的緩存區。
Buffer與字符編碼
Buffer實例一般用於表示編碼字符的序列,比如UTF-8、UCS2、Base64、或者十六進制編碼的數據,通過使用顯式的字符編碼,就可以在Buffer實例與普通的JavaScript字符串之間進行相互轉換。
const buf = Buffer.from(‘runoob‘,‘ascii‘); //輸出72756e6f6f62 console.log(buf.toString(‘hex‘)); //輸出cnVub29i console.log(buf.toString(‘base64‘));
Node.js目前支持的字符編碼包括:
ascII 僅支持7位ASCII數據。如果設置去掉高位的話,這種編碼是非常快。
utf8 多字節編碼的Unicode字符,許多網頁和其他文檔格式都使用UTF-8。
utf16le 2或4個字節,小字節編碼的Unicode字符。支持代理對(U+100000至U+10FFF)。
usc2 utf16le的別名。
base64 Base64編碼。
latin1 一種把Buffer編碼成一字節編碼的字符串的方式。
binary Latin1的別名。
hex 將兩個字節編碼為兩個十六進制字節。
創建Buffer類
Buffer提供了以下API創建Buffer類:
//創建一個長度為10、且用0填充的buffer const buf1 = buffer.alloc(10); //創建一個長度為10、且用0x1填充的buffer。 const buf2 = Buffer.alloc(10,1); //創建一個長度為10、且未初始化的Buffer。 //這個方法比調用Buffer.alloc()更快。 //但返回的Buffer實例可能包含舊數據。 //因此需要使用fill()或write()重寫。 const buf3 = Buffer.allocUnsafe(10); //創建一個包含[0x1, 0x2, 0x3]的Buffer const buf4 = Buffer.from([1,2,3]); //創建一個包含 UTF-8 字節 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。 const buf5 = Buffer.from(‘tést‘); // 創建一個包含 Latin-1 字節 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。 const buf6 = Buffer.from(‘tést‘, ‘latin1‘);
寫入緩沖區
語法:
寫入Node緩沖區的語法如下所示:
buf.write(string[, offset[, length]][,encoding])
參數:
根據encoding的字符編碼寫入string到buf中的offset位置。length參數是寫入的字節數。如果buf沒有足夠的空間保存整個字符串,則只會寫入string的一部分,只部分解碼的字符不會被寫入。
返回值:
返回實際寫入的大小。如果buffer空間不足,則只會寫入部分字符串。
從緩存區讀取數據
語法讀取Node緩沖區數據的語法如下:
buf.toString([encoding[, start[,end]]])
buf = Buffer.alloc(26); for(var i = 0; i < 26; i++) { buf[i] = i + 97; } console.log(buf.toString(‘ascii‘)); //輸出:abcdefghijklmnopqrstuvwxyz console.log(buf.toString(‘ascii‘, 0, 5)); // 輸出: abcde console.log(buf.toString(‘utf8‘, 0 ,5)); //輸出:abcde console.log(buf.toString(undefined, 0, 5)); //使用 ‘utf8‘ 編碼, 並輸出: abcde
將Buffer轉換為JSON對象
語法:將Node Buffer轉換為JSON對象的函數語法格式:
buf.toJSON()
當字符串化為一個Buffer實例時,JSON.stringify()會隱式地調用該toJson();
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); const json = JSON.stringify(buf); // 輸出: {"type":"Buffer","data":[1,2,3,4,5]} console.log(json); const copy = JSON.parse(json, (key, value) => { return value && value.type === ‘Buffer‘ ? Buffer.from(value.data) : value; }); // 輸出: <Buffer 01 02 03 04 05> console.log(copy);
緩沖區合並
語法:
Buffer.concat(list[, totalLength])
var buffer1 = Buffer.from((‘菜鳥教程‘)); var buffer2 = Buffer.from((‘www.runoob.com‘)); var buffer3 = Buffer.concat([buffer1,buffer2]); console.log("buffer3 內容: " + buffer3.toString());
緩沖區比較
語法:
buf.compare(otherBuffer);
var buffer1 = Buffer.from(‘ABC‘); var buffer2 = Buffer.from(‘ABCD‘); var result = buffer1.compare(buffer2); if(result < 0) { console.log(buffer1 + " 在 " + buffer2 + "之前"); }else if(result == 0){ console.log(buffer1 + " 與 " + buffer2 + "相同"); }else { console.log(buffer1 + " 在 " + buffer2 + "之後"); }
nodejs的基礎概念