nodejs技術摘要

一、認識nodejs

Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境(引自百度百科)。
在這裏插入圖片描述
我們都知道,瀏覽器是客戶端的JavaScript運行環境,相對的,nodejs就是服務端的JavaScript運行環境。

我們說nodejs是服務端的運行環境,並不意味着nodejs只能用於爲web提供後臺服務。nodejs實際上是讓JavaScript可以運行於瀏覽器之外,並且爲JavaScript提供了本地文件系統訪問、數據庫訪問,以及作爲web後臺服務所必需的http等接口,使JavaScript真正成爲一門可以用於web後端的編程語言。JavaScript在nodejs的環境下運行,就像Java在虛擬機環境下運行一樣。

因此,說nodejs是一門編程語言,這顯然是錯誤的。nodejs本身只是爲JavaScript提供了一個可以不在瀏覽器下運行的環境。既然是運行環境,那麼它必定包含能夠解析這門語言的編譯器或解釋器,nodejs的作者選擇了性能卓越的JavaScript引擎:V8(由C++編寫,主要用於Chromium和Chrome)。

僅僅有V8還是不夠的,因爲它只能解析JavaScript本身,無法爲其提供訪問操作系統其他服務的編程接口。要讓JavaScript能作爲服務端語言,至少要爲其提供訪問文件系統、數據庫等的能力,並且提供http服務,nodejs的作者Ryan Dahl以及技術社區爲此使用C++開發了一系列的模塊,如fs(文件系統模塊)、http(http服務模塊)、mysql(mysql數據庫模塊)、oracledb(Oracle模塊)等,這裏的fs和http模塊是核心模塊,內置於nodejs核心運行環境內,無需額外安裝。有了這些模塊,你可以用JavaScript訪問與操作系統相關的更多底層服務。
在這裏插入圖片描述
所以說,客戶端的JavaScript等於ECMAScript + DOM + BOM,而服務端的JavaScript等於ECMAScript + fs + mysql + oracledb + http + os(操作系統模塊) + net(TCP模塊) + …

有了這些模塊的支持,JavaScript纔算完全脫離了瀏覽器環境,具備了與操作系統交互的能力,因此它可以作爲web後端語言使用。

既然在nodejs環境下,JavaScript已經可以與操作系統交互了,那它就不限於作爲web後端語言了。此時的JavaScript還常用於編寫工具,比如常見的webpack、vue-cli、create-react-app等,甚至可以用於編寫桌面應用,如微軟旗下著名的基於electron的開發者工具vscode。

二、nodejs基本概念簡介

1. nodejs與npm

npm是nodejs“附贈”的包管理工具,當然它也是nodejs的作者推薦的包管理工具(nodejs現已交由npm的作者來維護)。當你安裝完nodejs,npm也就安裝完成了。

npm的主要作用是管理第三方包(如一個vue組件、一個react組件,或者打包工具webpack以及各種腳手架等,都稱爲一個包)。使用npm命令,你可以從npm服務器上下載別人上傳的第三方包或命令行到本地使用,也可以上傳自己的本地包供別人使用。

比如你想下載webpack,可以使用以下命令:

npm install webpack -g

install webpack表示要安裝webpack。-g參數表示這個包要安裝到nodejs的根目錄下,這樣可以作爲全局包使用。想要卸載已安裝的包,可以使用uninstall命令。

npm訪問的默認服務器地址是https://registry.npmjs.org/,上傳下載第三方包的目標服務器都是它。如果使用淘寶鏡像cnpm,訪問的是淘寶的服務器,一般來說,該服務器每10分鐘與官方服務器同步一次。

2. nodejs交互式解釋器(REPL)

不同於Java,JavaScript是一門腳本語言,它的執行不需要經過編譯,因此可以一行一行地執行。基於這個特點,nodejs爲JavaScript提供了一個交互式解釋器,用於在命令行即時編寫和執行JavaScript。

安裝完nodejs後,打開命令行,輸入node,敲擊回車,即可進入交互式執行環境:
在這裏插入圖片描述
出現一個大於號,表示已經進入交互式環境,接下來你可以輸入JavaScript語句,敲擊回車即可執行:
在這裏插入圖片描述
如果需要連續輸入多行代碼,可以按shift + 回車,解釋器會換行但暫不執行上一語句。

使用nodejs提供的交互式解釋器,可以方便地編寫並運行少量JavaScript代碼。如果代碼量稍大,可以將代碼保存在一個js文件中,然後用node命令執行該js文件,效果與在交互式環境下連續輸入這些代碼是一致的。

3. nodejs異步編程

nodejs使用了一個事件驅動、非阻塞式 I/O 的模型。它的非阻塞I/O是藉助事件循環實現的。

我們都知道,JavaScript是一門單線程語言。如果同步地執行所有的任務,諸如網絡請求、數據庫查詢這樣的操作將耗費大量的時間,導致程序性能極低。所以和在瀏覽器中一樣,nodejs也採用事件循環機制,通過回調函數來解決這個問題(圖片來自菜鳥教程)。
在這裏插入圖片描述
相比於客戶端JavaScript,服務端JavaScript具有更大的優勢。因爲客戶端瀏覽器類型不一,版本也有所差異,對JavaScript版本的支持性差異很大,給前端頁面開發帶來了很大的限制。但在服務端,nodejs版本由我們決定,所以我們可以更放心地使用高版本語法,比如Generator函數、async函數等,來實現異步編程。

此外,nodejs還提供了child_process模塊,爲JavaScript提供多進程支持。它比瀏覽器端的webworker更加強大,因爲webworker只是一種多線程實現,各個線程之間不具備通信能力,而由child_process創建的進程是可以通信的。

4. 全局對象global

我們知道,在瀏覽器環境下,全局對象是window。而在nodejs環境下,全局對象是global。

同window一樣,引用global的屬性也可以省略global。global的常見屬性包括:

  1. __filename:當前腳本的絕對路徑,含文件名
  2. __dirname:當前腳本所在的路徑,不含文件名
  3. setTimeout()、clearTimeout()、setInterval()、clearInetrval():用法與瀏覽器環境下一致
  4. console:控制檯對象,用法與瀏覽器下類似。不過瀏覽器環境下的控制檯由瀏覽器提供,而nodejs環境的控制檯通常指shell終端(即命令行窗口)。
  5. process:nodejs進程狀態對象。爲process綁定事件監聽,可以在nodejs的各個生命週期下執行操作。與nodejs交互的過程中,我們經常會訪問這個對象。

三、nodejs的幾個常用模塊

nodejs有很多模塊,這裏我們只對其中幾個最爲常用的進行一些簡介,以對nodejs有個大致的瞭解。

1. fs模塊

fs模塊是nodejs提供的文件系統模塊,提供一組類似於UNIX系統的文件操作API。引入fs模塊非常簡單:

let fs = require("fs");

得到了fs模塊後,我們就可以像下面這樣讀取文件系統的一個文件:

// 異步讀取
fs.readFile('input.txt', function (err, data) {
   if (err) {
       return console.error(err);
   }
   console.log("異步讀取: " + data.toString());
});

還可以以同步的方式來讀取文件:

// 同步讀取
var data = fs.readFileSync('input.txt');
console.log("同步讀取: " + data.toString());

實際上在Chrome瀏覽器中,JavaScript也具備讀取本地文件內容的能力,但是向文件系統中寫入內容是嚴格禁止的,因爲這會給客戶端安全帶來極大的安全隱患。而在nodejs環境下,由於是服務端,不存在這類安全問題,因此nodejs提供的fs模塊允許向文件系統寫入內容:

var fs = require("fs");

fs.writeFile('input.txt', '新內容', function(err) {
   if (err) {
       return console.error(err);
   }
   console.log("數據寫入成功!");
});

這會向當前文件夾下的input.txt寫入“新內容”這幾個字符,如果該文件不存在,將先創建它再寫入。

nodejs提供的文件系統操作接口使得它可以爲各種腳手架、打包工具等提供支持。比如vue或者react的腳手架,實際上就是利用nodejs提供的fs模塊,根據輸入的參數,複製事先寫好的模板文件到目標文件夾下。而打包工具,如webpack,則是對項目文件夾下的文件進行整合壓縮和輸出,也離不開nodejs提供的文件系統操作API。

2. web模塊

web模塊由若干子模塊組成,如http模塊、https模塊、ws模塊、net模塊(提供TCP連接)、url模塊等,爲web服務提供支持。有了這些模塊的支持,nodejs才能爲JavaScript提供完整的服務端環境。此外,在nodejs環境下,JavaScript還可以實現一個簡單的客戶端。

我們以一個簡單的例子來介紹web模塊(例子來自菜鳥教程):

首先我們在當前文件夾下新增一個index.html作爲服務端資源,它的內容很簡單:
index.html

<!DOCTYPE html>
<html>
  <body>
    Hello World!
  </body>
</html>

然後在同級目錄下新建server.js:
server.js

var http = require('http'); // http模塊
var fs = require('fs');  // 文件系統模塊
var url = require('url');  // url解析模塊

// 創建服務器
http.createServer( function (request, response) {  
   // 解析請求,包括文件名
   var pathname = url.parse(request.url).pathname;
   
   // 輸出請求的文件名
   console.log("Request for " + pathname + " received.");
   
   // 從文件系統中讀取請求的文件內容
   fs.readFile(pathname.substr(1), function (err, data) {
      if (err) {
         console.log(err);
         // HTTP 狀態碼: 404 : NOT FOUND
         // Content Type: text/html
         response.writeHead(404, {'Content-Type': 'text/html'});
      }else{             
         // HTTP 狀態碼: 200 : OK
         // Content Type: text/html
         response.writeHead(200, {'Content-Type': 'text/html'});    
         
         // 響應文件內容
         response.write(data.toString());        
      }
      //  發送響應數據
      response.end();
   });   
}).listen(8080);
 
console.log('Server running at http://127.0.0.1:8080/');

然後創建一個客戶端文件client.js:
client.js

var http = require('http');
 
// 用於請求的選項
var options = {
   host: 'localhost',
   port: '8080',
   path: '/index.html'  
};
 
// 處理響應的回調函數
var callback = function(response){
   // 不斷更新數據
   var body = '';
   response.on('data', function(data) {
      body += data;
   });
   
   response.on('end', function() {
      // 數據接收完成
      console.log(body);
   });
}
// 向服務端發送請求
var req = http.request(options, callback);
req.end();

打開命令行,輸入以下命令:
在這裏插入圖片描述
這樣我們的服務就運行起來了,運行網址是http://127.0.0.1:8080(如果你在瀏覽器地址欄輸入http://127.0.0.1:8080/index.html,就可以看到本地的index.html頁面)。

再打開一個命令行,然後輸入:
在這裏插入圖片描述
可以看到,即使沒有瀏覽器,我們也可以通過nodejs提供的http模塊,從http://127.0.0.1:8080這個網址下請求到index.html的內容。只是此時的html文件由於沒有瀏覽器的解析,只是作爲一串普通字符串返回的。基於這一點,你可以在nodejs環境下,用JavaScript寫一個爬蟲程序,主要過程就是不斷請求網頁,然後對取到的網頁字符串進行分析。

不同於Java,nodejs自行封裝了http服務,因此JavaScript運行在nodejs環境下時不需要其他的web容器(如Tomcat、Jetty等)。

3. 數據庫模塊

作爲服務端環境,訪問數據庫是必不可少的。nodejs爲各大數據庫提供對應的模塊,以使JavaScript可以訪問這些數據庫。常見的模塊如MySQL數據庫的mysql模塊,Oracle數據庫的oracledb模塊、MongoDB的mongodb模塊等。這些模塊不是nodejs的核心模塊,需要從npm下載安裝。

下面我們以Oracle數據庫連接來介紹nodejs的oracledb模塊的簡單用法(需要先安裝oracledb:npm install oracledb):

var oracledb = require('oracledb');

const param = {
    user: xxx,
    password: xxx,
    connectString: xxx(數據庫地址及實例)
};
const sql = "select * from USER where id=:1";
let userId = "123";  // 待查詢的用戶id

oracledb.getConnection(param, function(err, connection){
    if (err) {
        console.error(err.message);
        return;
    }
    console.log("數據庫連接成功");
    // 數組的userId元素將替換sql語句中的:1
    connection.execute(sql, [userId], function(err, res){
        if (err) {
            console.error(err.message);
        }

        console.log(JSON.stringify(res.rows[0]);
    })
})

使用不同的數據庫時,安裝對應的模塊即可。

總結

nodejs是JavaScript的服務端環境,它使得JavaScript不僅可以用於編寫web後端,還可以用於編寫各種工具、腳手架等。

nodejs用很多框架,如express、koa、eggjs等,在實際使用nodejs搭建web服務時,常常直接使用這些框架。nodejs的作者推薦使用中間件模式來開發web後臺服務,每個中間件就是一個處理函數,對請求進行一步處理,類似於Java的過濾器。這樣開發者就可以專注於業務邏輯的開發。

nodejs社區非常活躍,有大量可用的模塊,框架也是數不勝數,這裏只是nodejs初識篇,等以後在工作中深入使用後再進行更細緻的瞭解。

發佈了40 篇原創文章 · 獲贊 93 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章