Node.js學習總結

Node.js回調

Node.js異步編程的直接體現就是回調。javascript

阻塞代碼:

const fs = require("fs");
let data = fs.readFileSync('input.txt');

console.log(data.toString());
console.log("程序執行結束");

非阻塞代碼:

const fs = require("fs");
fs.readFile('input.txt',(error,data)=>{
    if(error) return console.log(error);
   console.log(data.toString()); 
});
console.log("程序執行結束");

Node.js事件循環

Node.js是單進程單線程應用程序,可是經過事件和回調支持併發,因此性能很是高。
進程:CPU執行任務的模塊。線程:模塊中的最小單元。java

Node.js使用事件驅動模型。
事件就是須要 eventEmitter.on 去綁定一個事件 經過 eventEmitter.emit 去觸發這個事件其次說的是 事件的 接收 和 發生 是分開的
事件驅動node

代碼以下:git

// 引入events 模塊
const events = require('events');
// 建立 eventEmitter 對象
let eventEmitter = new events.EventEmitter();

// 這裏既可使用.on  也可使用 .addListener
eventEmitter.on('dataReceived',(data) => {
    console.log(`接受的數據爲:${data}`);
});

// 觸發 dataReceived 事件
eventEmitter.emit('dataReceived');

繼承 EventEmitter

大多數時候咱們不會直接使用 EventEmitter,而是在對象中繼承它。包括 fs、net、 http 在內的,只要是支持事件響應的核心模塊都是 EventEmitter 的子類。github

若事件隊列中出現一個未綁定事件則觸發error事件,若未綁定 error事件則程序拋出異常結束執行 emitter.emit('error'); 程序會直接中斷,並拋出異常。web

Node.js Buffer緩衝區

該類用來建立一個專門存放二進制數據的緩存區。正則表達式

在v6.0之後,官方文檔裏面建議使用 Buffer.from() 接口去建立Buffer對象。

Buffer與字符串編碼

Buffer 實例通常用於表示編碼字符的序列,好比 UTF-8 、 UCS2 、 Base64 、或十六進制編碼的數據。 經過使用顯式的字符編碼,就能夠在 Buffer 實例與普通的 JavaScript 字符串之間進行相互轉換。編程

const buf = Buffer.from('hello','utf8');

// 輸出 hex 編碼後的內容
console.log(buff.toString('hex'));

// 輸出 base64 編碼後的內容
console.log(buf.toString('base64'));

建立 Buffer 類

經過 from 和 allocation(n:分配)數組

// 建立一個長度爲 十、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);

// 建立一個長度爲 十、且用 0x1 填充的 Buffer。 
const buf2 = Buffer.alloc(10, 1);

// 建立一個長度爲 十、且未初始化的 Buffer。
// 這個方法比調用 Buffer.alloc() 更快,
// 但返回的 Buffer 實例可能包含舊數據,
// 所以須要使用 fill() 或 write() 重寫。
const buf3 = Buffer.allocUnsafe(10);

// 建立一個包含 [0x1, 0x2, 0x3] 的 Buffer。
// 若是是字符串會被 0 覆蓋
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');

寫入緩衝區

buf.write(string,[offset],[length],[encoding]);
參數描述:緩存

  • string - 寫入緩衝區的字符串。
  • offset -開始寫入的索引值,默認爲0。
  • length -寫入的字節數,默認爲buffer.length。
  • encoding -使用的字符編碼,默認爲‘utf8’。
// 分配一個256字節的緩衝區
let buf = Buffer.alloc(256);
let len = buf.write("www.baidu.com");

console.log(`寫入的字節數數爲:${len}`);

緩衝區讀取數據

buf.toString([encoding],[start],[end]);
參數描述:

  • encoding - 使用的編碼。默認爲 'utf8' 。
  • start - 指定開始讀取的索引位置,默認爲 0。
  • end - 結束位置,默認爲緩衝區的末尾。
// 建立緩衝區並寫入26個小寫英文字母的ASCII碼
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 對象

buf.toJSON();

緩衝區合併

var buffer3 = Buffer.concat([buffer1,buffer2]);

拷貝緩衝區

buf.copy([targetBufffer],[targetStart],[sourceStart],{sourceEnd});
eg: buf2.copy(buf1,2) // 將buf2插入到buf1指定的位置上

Node.js Stream(流)

Stream 是一個抽象接口,Node 中有不少對象實現了這個接口。例如,對http 服務器發起請求的request 對象就是一個 Stream,還有stdout(標準輸出)。
全部的Stream對象繼承了 EventEmitter 類,因此擁有如下事件:

  • data - 當有數據可讀時觸發。
  • end - 沒有更多的數據可讀時觸發。
  • error - 在接收和寫入過程當中發生錯誤時觸發。
  • finish - 全部數據已被寫入到底層系統時觸發。

從流中讀取數據

const fs = require("fs");
let data = "";

// 建立可讀流
let readStream = fs.createReadStream('input.txt');
readStream.on('data',(chunk)=>{
    data += chunk;
})
readStream.on('end',()=>{
    console.log(data);
})
...

寫入流

var fs = require("fs");
var data = '百度官網地址:www.baidu.com';

// 建立一個能夠寫入的流,寫入到文件 output.txt 中
var writerStream = fs.createWriteStream('output.txt');

// 使用 utf8 編碼寫入數據
writerStream.write(data,'UTF8');

// 標記文件末尾
writerStream.end();

// 處理流事件 --> data, end, and error
writerStream.on('finish', ()=> {
    console.log("寫入完成。");
});

管道流

能夠實現大文件的複製。

const fs = require('fs');
let rs = fs.createReadStream('input.txt');
let ws = fs.createWriteStream('output.txt');

// 管道讀寫操做
// 讀取input.txt,將內容寫入到output.txt文件中
rs.pipe(ws);

鏈式流

鏈式是經過鏈接輸出流到另一個流並建立多個流操做鏈的機制。鏈式流通常用於管道操做。
接下來咱們就是用管道和鏈式來壓縮和解壓文件。

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 中的全局對象是 global,全部全局變量(除了 global 自己之外)都是 global 對象的屬性。
__filename :表示當前正在執行的腳本的文件名。(輸出文件所在的絕對路徑)
__ __dirnname __:表示當前執行腳本呢所在的目錄。
__ process __:它用於描述當前Node.js 進程狀態的對象。

Node.js經常使用工具

util是一個node。js核心模塊,提供經常使用的函數的集合。

  • util.inherits(constructor,superConstructor) 是一個實現對象間原型繼承的函數。(構造函數中的屬性和函數不會被繼承)。
  • util.inspect(object,[showHidden],[depth],[colors]) 是一個將任意對象轉換 爲字符串的方法,一般用於調試和錯誤輸出。
  • util.isArray(object) 判斷是否爲一個數組。
  • util.isRegExp(object) 判斷是否爲一個正則表達式。
  • util.isDate(object) 判斷是否爲一個日期。

Node.js 文件系統

Node.js 提供一組標準的文件操做API。

var fs = require("fs");

打開文件

fs.open(path,flags,[mode],callback);
  • path -文件路徑。
  • flags -文件打開的行爲。(r r+ rs[同步] w a[追加]...)
  • mode - 設置文件模式(權限),文件建立默認權限爲 0666(可讀,可寫)。
  • callback - 回調函數,帶有兩個參數如:callback(err, fd)。

獲取文件信息

如下爲經過異步模式獲取文件信息的語法格式:

fs.stat(path,callback) // 帶兩個參數:(err,stats)

能夠經過stats類中的提供方法判斷文件的相關屬性。

  • stats.isFile() 若是是文件返回 true,不然返回 false。
  • stats.isDirectory() 若是是目錄返回 true,不然返回 false。
  • stats.isBlockDevice() 若是是塊設備返回 true,不然返回 false。
  • stats.isCharacterDevice() 若是是字符設備返回 true,不然返回 false。
  • stats.isSymbolicLink() 若是是軟連接返回 true,不然返回 false。
  • stats.isFIFO() 若是是FIFO,返回true,不然返回 false。FIFO是UNIX中的一種特殊類型的命令管道。
  • stats.isSocket() 若是是 Socket 返回 true,不然返回 false。

寫入文件

如下爲異步模式下寫入文件的語法格式:

fs.writeFile(file, data,[options], callback)

若是文件存在,該方法寫入的內容會覆蓋舊的文件內容。

參數使用說明以下:

  • file - 文件名或文件描述符。
  • data - 要寫入文件的數據,能夠是 String(字符串) 或 Buffer(流) 對象。
  • options - 該參數是一個對象,包含 {encoding, mode, flag}。默認編碼爲 utf8, 模式爲 0666 , flag 爲 'w'
  • callback - 回調函數,回調函數只包含錯誤信息參數(err),在寫入失敗時返回。

讀取文件

如下爲異步模式下讀取文件的語法格式:

fs.read(fd, buffer, offset, length, position, callback)

該方法使用了文件描述符來讀取文件。

參數使用說明以下:

  • fd - 經過 fs.open() 方法返回的文件描述符。
  • buffer - 數據寫入的緩衝區。
  • offset - 緩衝區寫入的寫入偏移量。
  • length - 要從文件中讀取的字節數。
  • position - 文件讀取的起始位置,若是 position 的值爲 null,則會從當前文件指針的位置讀取。
  • callback - 回調函數,有三個參數err, bytesRead, buffer,err 爲錯誤信息, + bytesRead 表示讀取的字節數,buffer 爲緩衝區對象。

關閉文件

fs.close(fd,callback)

打開文件,讀取文件,關閉文件示例代碼:

var fs = require("fs");
var buf = new Buffer(1024);

console.log("準備打開文件!");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("文件打開成功!");
   console.log("準備讀取文件!");
   fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
      if (err){
         console.log(err);
      }

      // 僅輸出讀取的字節
      if(bytes > 0){
         console.log(buf.slice(0, bytes).toString());
      }

      // 關閉文件
      fs.close(fd, function(err){
         if (err){
            console.log(err);
         } 
         console.log("文件關閉成功");
      });
   });
});

刪除文件

fs.unlink(path,callback);

建立目錄

fs.mkdir(path,[mode],callback);

讀取目錄

fs.readdir(path,callback);  // callback(err,files[文件列表])

刪除目錄

fs.rmdir(path,callback);

Node.js 模塊

os模塊

os模塊提供了一些基本的系統操做函數。

var os = require("os");

// CPU 的字節序
console.log('endianness : ' + os.endianness());

// 操做系統名
console.log('type : ' + os.type());

// 操做系統名
console.log('platform : ' + os.platform());

// 系統內存總量
console.log('total memory : ' + os.totalmem() + " bytes.");

// 操做系統空閒內存量
console.log('free memory : ' + os.freemem() + " bytes.");

path模塊

var path = require("path");

// 格式化路徑
console.log('normalization : ' + path.normalize('/test/test1//2slashes/1slash/tab/..')); // normalization : /test/test1/2slashes/1slash

// 鏈接路徑
console.log('joint path : ' + path.join('/test', 'test1', '2slashes/1slash', 'tab', '..')); // joint path : /test/test1/2slashes/1slash

// 轉換爲絕對路徑
console.log('resolve : ' + path.resolve('main.js')); // resolve : /web/com/1427176256_27423/main.js

// 路徑中文件的後綴名
console.log('ext name : ' + path.extname('main.js')); // ext name : .js

DNS模塊

dns.lookup(hostname,[options(4|6)],callback); // 解析域名

var dns = require('dns');

dns.lookup('www.github.com', function onLookup(err, address, family) {
   console.log('ip 地址:', address);
   dns.reverse(address, function (err, hostnames) {
   if (err) {
      console.log(err.stack);
   }

   console.log('反向解析 ' + address + ': ' + JSON.stringify(hostnames));
   });  
});
相關文章
相關標籤/搜索