【核心模組】node.js

Eric_zhang發表於2019-04-17

核心模組

全域性物件與全域性變數

  • node環境中,全域性物件為global;瀏覽器環境中,全域性物件時window
  • 所有全域性變數均掛載在全域性物件上,作為全域性物件的屬性,其中包含:
    • 顯式定義全域性物件的屬性
    • 隱式定義的變數(沒有定義直接賦值的變數)
    • 這裡建議使用 var、let、const 定義變數以避免引入全域性變數,因為全域性變數會汙染 名稱空間,提高程式碼的耦合風險。

常用的全域性變數

process:描述當前 Node.js 程式狀態 的物件,提供了一個與作業系統的簡單介面

  • process.argv是命令列引數陣列,第一個元素是 node,第二個元素是指令碼檔名,從第三個元素開始每個元素是一個執行引數
  • process.nextTick(callback)將callback放入非同步micro task佇列中,如果callback的執行時間需要很長,則通過這個方式可以不阻塞當前主執行緒 console:控制檯標準輸出
  • console.log()常規輸出,也可以使用類似c語言printf()命令的佔位符輸出console.log('%d year', 1993)
  • console.error()輸出錯誤
  • console.trace()輸出當前呼叫棧

事件驅動 events模組

事件發射與監聽器:events.EventEmitter 物件

  • EventEmitter.on(event, listener) 為指定事件註冊一個監聽器,接受一個字串event 和一個回撥函式listener
  • EventEmitter.emit(event, [arg1], [arg2], [...]) 發射 event 事件,傳遞若干可選引數到事件監聽器的參數列
  • EventEmitter.once(event, listener) 為指定事件註冊一個單次監聽器,即監聽器最多隻會觸發一次,觸發後立刻解除該監聽器
  • EventEmitter.removeListener(event, listener) 移除指定事件的某個監聽器,listener 必須是該事件已經註冊過的監聽器
  • EventEmitter.removeAllListeners([event]) 移除所有事件的所有監聽器, 如果指定 event,則移除指定事件的所有監聽器
      var events = require('events');
      var emitter = new events.EventEmitter();
      emitter.on('event', function(arg1, arg2) { console.log('listener1', arg1, arg2);
      });
      emitter.on('event', function(arg1, arg2) { console.log('listener2', arg1, arg2);
      });
      emitter.emit('someEvent', 'hello', 'world');
      // listener1 hello world
      // listener2 hello world
    複製程式碼

大多數時候我們不會直接使用 EventEmitter,而是在物件中繼承它。包括 fs、net、 http 在內的,只要是支援事件響應的核心模組都是 EventEmitter 的子類,模組的例項物件可以直接使用on()方法監聽事件

檔案系統 fs模組

  • fs.readFile() 非同步讀取檔案內容
  • fs.readFileSync() 同步讀取檔案內容
  • fs.open() 開啟檔案
  • fs.read() 讀取檔案(從指定的檔案描述符 fd 中讀取資料並寫入 buffer 指向的緩衝區物件),需要先執行fs.open()開啟檔案後,在其回撥函式中使用fs.read().一般來說,除非必要,否則不要使用這種方式讀取檔案,因為它要求你手動管理緩衝區 和檔案指標,尤其是在你不知道檔案大小的時候,這將會是一件很麻煩的事情。
      var fs = require('fs');
      fs.open('content.txt', 'r', function(err, fd) { 
          if (err) {
              console.error(err);
              return; 
          }
      var buf = new Buffer(8);
      fs.read(fd, buf, 0, 8, null, function(err, bytesRead, buffer) {
          if (err) { 
              console.error(err); 
              return;
          }
              console.log('bytesRead: ' + bytesRead);
              console.log(buffer);
          })
      });
      // bytesRead: 8
      // <Buffer 54 65 78 74 20 e6 96 87>
    複製程式碼

HTTP 模組

HTTP模組封裝了一個HTTP伺服器與HTTP客戶端

HTTP伺服器(基於http.Server物件實現)

http.createServer()會建立一個http.Server例項物件

var http = require('http');
http.createServer(function(req, res) { 
    res.writeHead(200, {'Content-Type': 'text/html'}); 
    res.write('<h1>Node.js</h1>');
    res.end('<p>Hello World</p>');
}).listen(3000);
console.log("HTTP server is listening at port 3000.");
複製程式碼

http.createServer的回撥函式中的兩個引數 req 和res,分別是 http.ServerRequest和http.ServerResponse 的例項,表示請求和響應資訊

http.ServerRequest 是 HTTP 請求的資訊,所有的業務邏輯都是根據請求傳遞的內容展開的,所以是後端開發者最關注的內容

包含一些常用屬性:

【核心模組】node.js
http.ServerRequest的事件:

  • data :當請求體資料到來時,該事件被觸發。該事件提供一個引數 chunk,表示接 收到的資料。如果該事件沒有被監聽,那麼請求體將會被拋棄。該事件可能會被調 用多次
  • end :當請求體資料傳輸完成時,該事件被觸發,此後將不會再有資料到來
  • close: 使用者當前請求結束時,該事件被觸發
獲取GET請求內容:使用url.parse來解析get請求中url後面的引數
var http = require('http'); 
var url = require('url'); 
var util = require('util');
http.createServer(function(req, res) { 
    res.writeHead(200, {'Content-Type': 'text/plain'}); 
    res.end(util.inspect(url.parse(req.url, true))); // util.inspect是將物件轉換成字串的工具函式
}).listen(3000);
複製程式碼
獲取POST請求內容

使用http.ServerRequest的data事件收集post請求體內容,然後使用querystring.parse來解析post請求傳過來的內容

var http = require('http');
var querystring = require('querystring'); 
var util = require('util');
http.createServer(function(req, res) { 
    var post = '';
    req.on('data', function(chunk) { 
        post += chunk;
    });
    req.on('end', function() {
        post = querystring.parse(post); 
        res.end(util.inspect(post));
    });
}).listen(3000);
複製程式碼

不要在真正的生產應用中使用上面這種簡單的方法來獲取 POST 請 求,因為它有嚴重的效率問題和安全問題,這只是一個幫助你理解的示例。

http.ServerResponse 是返回給客戶端的資訊,決定了使用者最終能看到的結果

三個重要的成員函式,用於返回響應頭、響應內容以及結束 請求:

  • response.writeHead(statusCode, [headers]):向請求的客戶端傳送響應頭。 statusCode 是 HTTP 狀態碼,如 200 (請求成功)、404 (未找到)等。headers 是一個類似關聯陣列的物件,表示響應頭的每個屬性。該函式在一個請求內最多隻 能呼叫一次,如果不呼叫,則會自動生成一個響應頭
  • response.write(data, [encoding]):向請求的客戶端傳送響應內容。data 是 一個 Buffer 或字串,表示要傳送的內容。如果 data 是字串,那麼需要指定 encoding 來說明它的編碼方式,預設是 utf-8。在 response.end 呼叫之前, response.write 可以被多次呼叫
  • response.end([data], [encoding]):結束響應,告知客戶端所有傳送已經完 成。當所有要返回的內容傳送完畢的時候,該函式 必須 被呼叫一次。它接受兩個可 選引數,意義和 response.write 相同。如果不呼叫該函式,客戶端將永遠處於 等待狀態

HTTP 客戶端(作為客戶端向伺服器發起請求)

  • http.request(options, callback) 發起 HTTP 請求
    • option 是 一個類似關聯陣列的物件,表示請求的引數,callback 是請求的回撥函式
    • callback 傳遞一個引數,為http.ClientResponse的例項
    • http.request 返回一個http.ClientRequest的例項
      var http = require('http');
      var querystring = require('querystring');
      var contents = querystring.stringify({
      name: 'byvoid',
      email: 'byvoid@byvoid.com',
      address: 'Zijing 2#, Tsinghua University',
      });
      var options = {
      host: 'www.byvoid.com',
      path: '/application/node/post.php', method: 'POST',
      headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
              'Content-Length' : contents.length
          }
      };
      var req = http.request(options, function(res) { res.setEncoding('utf8');
      res.on('data', function (data) {
              console.log(data);
          });
      });
      req.write(contents);
      req.end(); //  不要忘了通過 req.end() 結束請求,否則伺服器將不會收到資訊
    複製程式碼
  • http.get(options, callback) get請求的簡化版,唯一的區別在於http.get 自動將請求方法設為了 GET 請求,同時不需要手動呼叫 req.end()
http.ClientRequest 物件(http.request()返回的例項物件)

物件含有的方法:

  • write()伺服器傳送請求體
  • end()寫結束以後必須呼叫 end 函式以通知伺服器,否則請求無效
http.ClientResponse 物件(http.request()回撥函式中的引數為該例項物件)

提供三個事件:

  • data 資料達到是觸發
  • end 資料傳輸結束後觸發
  • close 連線結束後觸發
    【核心模組】node.js

三個特殊的函式:

  • response.setEncoding([encoding]):設定預設的編碼,當 data 事件被觸發時,資料將會以 encoding 編碼。預設值是 null,即不編碼,以 Buffer 的形式儲存。常用編碼為 utf8
  • response.pause():暫停接收資料和傳送事件,方便實現下載功能
  • response.resume():從暫停的狀態中恢復

相關文章