前端筆記之NodeJS(一)初識NodeJS&內置模塊&特點

来源:https://www.cnblogs.com/rope/archive/2019/04/19/10724604.html
-Advertisement-
Play Games

一、NodeJS簡介 NodeJS是開發伺服器後臺的東西,和PHP、JavaEE、python類似,和傳統的瀏覽器的關註DOM的JS完全不同,將JavaScript觸角伸到了伺服器端。內核是Chrome瀏覽器的V8引擎,解析JavaScript的效率是非常快的。 創始人。 在不升級伺服器配置的情況下 ...


一、NodeJS簡介

NodeJS是開發伺服器後臺的東西,和PHPJavaEEpython類似,和傳統的瀏覽器的關註DOMJS完全不同,將JavaScript觸角伸到了伺服器端。內核是Chrome瀏覽器的V8引擎,解析JavaScript的效率是非常快的。

 創始人。

在不升級伺服器配置的情況下,如何用軟體手段來提升伺服器性能:Ryan Dahl大致的感覺到瞭解決問題的關鍵是要通過事件驅動和非同步I/O來達成目的。

傳統的伺服器模型:當我們做I/O操作的時候(I表示讀,O表示寫),CPU被磁碟操作阻塞了,此時我們稱這叫做“同步I/Osynchronous I/O),阻塞I/Oblocking I/O)”。

CPU會經常對磁碟驅動發出I/O命令

此時磁碟特別忙,CPU就歇著了。造成了資源浪費。上圖這種模式叫做“同步I/O”。

同步(synchronous):當系統遇見了一個需要耗費大量時間的事情的時候,選擇死等。
非同步(Asynchronous):當系統遇見了一個需要耗費大量時間的事情的時候,不死等,先做後面的事情,耗時事情做完之後,執行回調函數。

 

PHP做一個例子:下麵程式中紅色部分是I/O操作,此時CPU被阻塞,此時為什麼不限做藍色計算部分?等紅色部分做完了用“回調函數”來顯示文件內容多好。

<?php
    //讀取文件
    $myfile = fopen("txt.txt", "r");
    //列印文件記憶體
    echo fread($myfile, filesize("txt.txt"));

    for($i = 2; $i < 100; $i++){
        $count = 0;
        for($j = 1; $j <= $i; $j++){
            if($i % $j == 0){
                $count++;
            }
        }
        if($count == 2){
            echo $i."<br/>";
        }
    }

    fclose($myfile);
?>

V8引擎來了。V8滿足他關於高性能Web伺服器的想象:

● 沒有歷史包袱,沒有同步I/O。不會出現一個同步I/O導致事件迴圈性能急劇降低的情況。

V8性能足夠好,遠遠比PythonRuby等其他腳本語言的引擎快。

JavaScript語言的閉包特性非常方便,比C中的回調函數好用。

 創始人Ryan Dahl想到了用V8引擎內核,用JS當做語言去開發服務端程式。

 

 

下麵是Nodejs的畫風,Nodejs不是語言,語言是JavaScriptNodejs是一個平臺,讓我們的JS可以運行在服務端的平臺。

var fs = require("fs");
fs.readFile("./txt.txt" ,function(err, data){
    console.log(data.toString());
})

for(var i = 2; i < 100; i++){
    count = 0;
    for(var j = 1; j <= i;j++){
        if(i % j == 0){
            count++;
        }
    }
    if(count == 2){
        console.log(i)
    }
}

紅色的I/O操作沒有將藍色計算操作阻塞,稱為“Non-Blocking I/O”非阻塞I/O。紫色語句是回調函數。

 

官網:https://nodejs.org/en/

中文:http://nodejs.cn/

NodeJS是一個JS運行環境,它構建在chromeV8引擎上。使用了事件驅動、非阻塞I/O模型,使它輕量並且方便。NodeJS有一個全球最大的包生態系統npm

 

Node.js使JavaScript的觸角伸到了伺服器開發中,在Node的世界中,我們關心的不再是用JS操作網頁上的DOM、製作交互動畫、表單驗證……而是伺服器端的事情:HTTP請求的處理、GET請求和POST請求、資料庫增刪改查、cookiesession等等。

 

Node.js的特點:單線程、非阻塞非同步I/O、事件驅動。

NodejsJS的運行環境,它構建在ChromeV8引擎上。

Nodejs是一個小極客,追求極致的伺服器性能,劍走偏鋒的產物。

與其很多服務員閑著,還不如一個服務員100%的工作。

 


二、NodeJS的安裝

 

NodeJSJava虛擬機一樣,是跨平臺的,也就是說只要寫一份代碼,可以運行在任何平臺上。

 

NodeJS官網下載:

 

 

 

安裝的歡迎界面

 

 

同意協議

 

 

安裝路徑全程不能有中文。

事實上很多軟體公司已經去中文化,文檔都是英語的文件名,文件夾都是英語的。

 

 

這個界面不需要改變任何的配置,但是要知道:這裡安裝了4個東西。

 

 

 

點擊下一步就開始安裝了

 

 

系統的防火牆,選擇是

 

 

nodejs已經被成功的安裝。

 

安裝完畢之後,按windows鍵加R鍵(run),輸入cmd(表示commond命令)按回車:

 

 

這是系統的密令提示符,可以輸入類似DOS的命令。但是現在要輸入

node -v

追求以下真理,安裝過程,到底發生了什麼?發現了一個Nodejs程式:

我們發現系統的環境變數中,已經添加了這個路徑:

系統的環境變數可以保證我們的node在任意CMD盤符下可以被運行

nodejswindows中是一個exe程式。


 

三、運行Nodejs程式

c盤創建一個nodejs_study文件,然後寫01.js文件

 

將文件拖拽到瀏覽器中不能執行的。

因為js的執行需要宿主環境(runtime),目前我們只知道一個環境:瀏覽器+HTML環境。

想要運行01.js程式:

<html>
<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>
<body>
</body>
<script type="text/javascript" src="01.js"></script>
</html>

瀏覽器會渲染html就能執行js

 

NodeJS是一個全新的JS宿主環境runtime。也就是說可以用node運行js程式,而不需要html和瀏覽器。

打開CMD,首先註意游標所在盤符位置:

 

01.js文件不在C:\Users\admin>中,而是在C:\nodejs_study,所以要用cd命令來切換游標所在盤符位置:

 

當用cd切換到01.js所在目錄時,此時可以用node命令執行js文件:

 

 

也就是說,運行js文件的時候:

① 要保證游標所在位置正確

② 運行誰,就node誰。

 

為了快速打開正確游標所在位置,此時有奇淫技巧:

 

要求大家,在運行node程式的時候,必須進入準確的盤符,不能使用絕對路徑

 

最快的運行node程式的方法就是使用visual studio code,或者webstrom直接按F5IDE(編程工具)內置的控制台會輸出結果。

 

CMD的命令:
cls
清屏。

cd ..
回退到上一級文件夾

cd 文件夾名字
進入這個文件夾

dir
列出當前目錄中所有的文件

↑上箭頭
重覆上一條指令。

四、NodeJS內置模塊

4.1 fs模塊

NodeJS沒有自己的語法,JS能寫什麼,node就能運行什麼

但是要註意,僅限於JS語言核心部分。DOMBOM不能用,node沒有瀏覽器的那些東西

document.getElementById("box");
window
alert()

 

但是可以用定時器

setInterval(function(){
    console.log(Math.random());
},100)

ctrl+c可以打斷Nodejs程式的執行。

 

Nodejs中提供了很多內置模塊,幫助我們開發,可以提供瀏覽器所不具備的功能,模塊是內置的,不需要額外安裝。從fs內置模塊學起,fsfile system文件系統的意思,提供了對文件的所有操作

// require表示得到,引入fs內置模塊,file system文件系統模塊
var fs = require("fs");

//fs模塊有個方法叫readFile,可以非同步讀文件內容
//這個函數是非同步函數,也就是說讀取文件不會阻塞CPU執行,所以讀取到的內容通過回調函數返回
//err參數:錯誤信息,沒有錯誤將返回null
//data參數:返迴文件的內容
fs.readFile("./test1.txt",function(err,data){
    if(err){
        console.log("文件讀取錯誤!");
        return;
    }
    //讀取的是信息流,是Buffer是緩衝的二進位,用toString()轉為字元串
    console.log(data.toString());
});

利用fs.readFile()這個API來讀取文件,並且是非同步讀取文件,這裡註意兩個事情:

1) 第一個參數是路徑,必須以"./"開頭,表示從相對於當前的cmd盤符位置去讀取文件。

2) 第二個參數是回調函數,註意回調函數中提供了兩個參數,分別是errdata。註意,nodejs中的所有回調函數的第一個參數都是err對象,表示錯誤。如果沒有錯誤,這個對象是null

 

要會看APIhttps://nodejs.org/dist/latest-v6.x/docs/api/

 

var fs = require("fs");

fs.readFile("./test1.txt",function(err,data){
    console.log(data.toString());
});

fs.readFile("./test2.txt",function(err,data){
    console.log(data.toString());
});

fs.readFile("./test3.txt",function(err,data){
    console.log(data.toString());
});

 

在Nodejs中要適應回調套回調函數的寫法:

var fs = require("fs");

fs.readFile("./test1.txt",function(err,data){
    console.log(data.toString());

    fs.readFile("./test2.txt",function(err,data){
        console.log(data.toString());

        fs.readFile("./test3.txt",function(err,data){
            console.log(data.toString());
        });
    });
});

4.2 http模塊

http模塊,Nodejs可以開發伺服器。創建伺服器的API要自己背誦記憶一下,不過,後面講解Express,極大簡化伺服器的創建:

var http = require('http'); //讀取內置http模塊,這個模塊提供了http服務

//創建一個伺服器,是非同步函數,事實上node中基本所有函數都是非同步的
var server = http.createServer(function(req,res){
    //req表示request用戶的請求
    //res表示response伺服器的響應

    //設置響應報文頭,讓類型變為html並且是utf8編碼
    res.setHeader("Content-type", "text/html;charset=UTF8");
    //頁面上輸出內容,輸出內容用write,end表示結束!
    res.end("<h1>你好,我是nodejs開發的伺服器!</h1>");
});

//監聽3000埠,預設是80埠,但80被Apache占用了,所以改用3000
server.listen(3000,function(err){
    if(err){
        console.log("伺服器開啟失敗!");
        return;
    }
    console.log("伺服器開啟成功,在3000埠,快打開瀏覽器看看吧!");
});

 

此時CMD會被掛起,按ctrl+c打斷(打斷之後,伺服器也打不開了)

 

我們來驗證程式確實在伺服器上運行的: 

var http = require('http');

var server = http.createServer(function(req,res){
    res.setHeader("Content-type", "text/html;charset=UTF8");
    res.end("<h1>你好,我是nodejs開發的伺服器!已經誕生了"+ (3 + 3) +"年了</h1>");
});

server.listen(3000);

 

在瀏覽器中,看不到後端node的源代碼:

 

原因是Nodejs執行在伺服器端,語句在伺服器被執行、編譯,此時發給瀏覽器的就是執行之後、編譯後的純文本了,不含有計算的。

 

兩個問題:

1、我用Nodejs搭建的伺服器,訪問者也必須安裝nodejs嗎。

不需要的,因為nodejs是伺服器程式,生成的內容僅需要瀏覽器就能訪問

 

2、我們用高級ES6語法書寫Nodejs程式,必須用高級瀏覽器訪問嗎。

不需要的,因為Nodejs程式不在瀏覽器執行。

 

req表示request用戶的請求,訪問者的所有必要信息在req中存儲,比如

req.url
表示訪問路徑
req.connection.remoteAddress
表示訪問者的ip地址
res表示response伺服器的響應,伺服器應該給與的反饋。
res.setHeader("Content-type", "text/html;charset=UTF8");
設置HTTP下行報文體

res.end() res.write()負責寫下行報文體(就是網頁)。

res.end()結束響應,告訴客戶端所有消息已經發送完畢,當所有要返回的內容發送完畢時,該函數必須被調用一次,如果不調用該函數,客戶端將永遠處於等待狀態。

 

var http = require('http');

var server = http.createServer((req,res)=>{
    res.setHeader("Content-type", "text/html;charset=UTF8");

    //頁面顯示的內容
res.write("<h1>hello world!</h1>");
    res.write("<ul>");
    res.write("<li>Nodejs</li>");
    res.write("<li>npm</li>");
    res.write("<li>Express</li>");
    res.write("<li>Mongodb</li>");
    res.write("</ul>");
    res.end(); //必須結束,否則本次操作不結束,瀏覽器顯示為載入中
});

server.listen(3000);

五、NodeJS特點

5.1單線程

寫一段程式,證明NodeJS是單線程的:

var http = require("http");

//在伺服器外面定義一個變數a
var a = 0;

var server = http.createServer(function(req,res){
a++;
    res.end(a.toString());
});

server.listen(3000)

我們發現不是每個訪問者來了都有新的a值,而是全班共用一個a,每個人訪問的時候看到的都是已經被刷過的a值。

 

var http = require("http");

var server = http.createServer(function(req,res){
    var a = ~~(Math.random() * 1000);

    if(a == 38){
        throw new Error("有人踩地雷了,此人IP:" + req.connection.remoteAddress);
    }

    res.end("<h1>"+ a +"</h1>");
});

server.listen(3000)

JavaPHP或者.net等伺服器端語言中,會為每一個客戶端連接創建一個新的進程。而每個進程需要耗費大約2MB記憶體。也就是說,理論上一個8GB記憶體的伺服器可以同時連接的最大用戶數為4000個左右。要讓Web應用程式支持更多的用戶,就需要增加伺服器的數量,而Web應用程式的硬體成本當然就上升了。

打個比喻,PHP假如是一個餐館,那麼就是一個這樣的餐館:來一個用戶,它就給你新招聘一個服務員,專門伺候你。你點菜的時候,這個服務員幫你點菜,你開始吃了,你這個服務員就閑置。這就造成了大量的浪費,憑什麼閑置服務員,為什麼不去服務別人?

 

Node.js不為每個客戶連接創建一個新的線程,而僅僅使用一個線程當有用戶連接了,就觸發一個內部事件,通過非阻塞I/O、事件驅動機制,讓Node.js程式巨集觀上也是並行的。使用Node.js,一個8GB記憶體的伺服器,可以同時處理超過4萬用戶的連接。

 打個比喻,Node.js假如是一個餐館,那麼就是一個這樣的餐館:總共就一個服務員,A用戶來了,幫A用戶點菜,B用戶來了,B用戶稍微被阻塞一下,A點完菜之後,廚師開始做,服務BB開始點菜,點菜的時候A的菜做好了,給B點完菜之後再去給A端菜,A開始吃,此時C來了,說了句歡迎光臨之後,“您看看菜單先”,就去給B端菜去了,B開始吃上了,此時C開始點菜……。

 

 微觀上,ABC不是並行的,但是巨集觀上他們是並行的!

 另外,單線程的帶來的好處,還有操作系統完全不再有線程創建、銷毀的時間開銷。

 

 


5.2非同步I/O特性

再來一個案例,用戶訪問頁面的時候,伺服器要讀取兩個文件,此時用console查看唯一的服務員如何工作:

var server = http.createServer((req,res) => {
     //用戶訪問的時候執行的語句。
    console.log(req.connection.remoteAddress + "進門了!我招呼他去!");
    res.setHeader("Content-Type","text/html;charset=UTF8");

    console.log(req.connection.remoteAddress + "用戶開始讀1號文件");
     fs.readFile("./test1.txt",(err,data1) => {
         console.log(req.connection.remoteAddress + "用戶讀完畢1號文件,開始讀2號文件");
         fs.readFile("./test2.txt",(err,data2) => {
             console.log(req.connection.remoteAddress+"用戶讀完2號文件,開始發送response");
             
             res.write("<h1>" + data1.toString() +"</h1>");
             res.write("<h1>" + data2.toString() +"</h1>");
             res.end("");
         });
     });
});

你I/O的時候CPU並沒有被阻塞,去伺候別人,當別人也I/O了此時執行你的回調函數。

綜上所述,nodejs是一個服務員在伺候所有人,所以擅長I/O越多的業務。I/O越多,效率越高,nodejs不會錯亂,採用就是事件環機制,也叫事件驅動機制,nodejs不擅長計算多的業務,因為給一個用戶計算去了,此時唯一的線程就被阻塞了,其他用戶進來就等待。

 

比如下麵的程式,紅色的部分是計算水仙花數,計算很複雜,但是是同步的,所以小服務員就被阻塞了:

var server = http.createServer((req,res) => {
     //用戶訪問的時候執行的語句。
    console.log(req.connection.remoteAddress + "進門了!我招呼他去!");
    console.log(req.connection.remoteAddress + "開始計算水仙花數了!");

    for(var i = 100 ; i <= 999 ; i++){
        // 給三位數拆分成三個單獨的數
        var ge = i % 10;
        var shi = parseInt(i / 10) % 10;
        var bai = parseInt(i / 100);
        // 計算三次方的和
        var sum = Math.pow(ge,3) + Math.pow(shi,3) + Math.pow(bai,3);
        // 判斷輸出
        if(sum == i){
            console.log(req.connection.remoteAddress + "計算出了水仙花數" + i);
        }
    }
    res.setHeader("Content-Type","text/html;charset=UTF8");

    console.log(req.connection.remoteAddress + "開始讀取文件");
     fs.readFile("./test1.txt",(err,data1) => {
         console.log(req.connection.remoteAddress + "讀取文件完畢,開始輸出響應流");
        res.write("<h1>" + data1.toString() +"</h1>");
        res.end("");
     });
});

5.3事件驅動

事件驅動是nodejs的底層機制,我們只需瞭解nodejs不會“上錯菜”,原因就是事件驅動,有一個事件環。

 

Node中,客戶端請求建立連接,提交數據等行為,會觸發相應的事件。在Node中,在一個時刻,只能執行一個事件回調函數,但是在執行一個事件回調函數的中途,可以轉而處理其他事件(比如,又有新用戶連接了),然後返回繼續執行原事件的回調函數,這種處理機制,稱為“事件環”機制。

Node.js底層是C++V8也是C++寫的)。底層代碼中,近半數都用於事件隊列、回調函數隊列的構建。用事件驅動來完成伺服器的任務調度,這是鬼才才能想到的。

 

 

 

2013年開始,Nodejs突然間火爆,因為Nodejs的工作流工具火了!

我們現在學習nodejs的意義,已經從學習HTTP伺服器的構建,變為學習它的工作流工具。

公司的伺服器都是PHPJSPPython.net製作的,nodejshttp服務是很少的。但是,每一個前端必須會Nodejs,因為之後用的所有的東西webpackbabelgulpgrunt等等都是基於nodejs的。

 


 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 處理數值,為每三位數加一個逗號,相容浮點型數值 以 和 為例 通過內置方法實現 通過正則表達式 利用正則表達式來處理的思路: 整數和浮點數是有差別的,整數從最右邊開始算,浮點數要從小數點'.'開始算 字元串分為兩部分,右邊是3 n位數字,左邊的部分添加','。n = {1,} 右邊的部分很好匹配: ...
  • jQuery選擇器一、基本選擇器: 1、ID選擇器 #id 描述:根據給定的id匹配一個元素, 返回單個元素(註:在網頁中,id名稱不能重覆) 2、類選擇器 .class 描述:根據給定的類名匹配元素,返回元素集合 3、元素選擇器 element 描述:根據給定的元素名匹配元素,返回元素集合 4、* ...
  • 一、為什麼JavaScript是單線程? JavaScript語言的一大特點就是單線程,也就是說,同一個時間只能做一件事。那麼,為什麼JavaScript不能有多個線程呢?這樣能提高效率啊。 JavaScript的單線程,與它的用途有關。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動 ...
  • v-bind和v-model的區別 1.v-bind用來綁定數據和屬性以及表達式,縮寫為':' 2.v-model使用在表單中,實現雙向數據綁定的,在表單元素外使用不起作用 v-bind和v-model的區別 什麼是 mvvm? MVVM 是 Model-View-ViewModel 的縮寫。mvv ...
  • 其實這種功能,網上相關的代碼多的是,我也是因為今天正好要用到這個功能,所以臨時寫了下,放這裡保存下,以便將來自己或者別人用的上吧。 當然我寫的是一個hta文件。下麵是完整js代碼,都是調用activex控制項去做事,所以也沒有考慮瀏覽器相容什麼的。 代碼主要分為: 1.選擇目標文件夾 2.遍歷目標文件 ...
  • javascript基礎篇詳情 2019-04-19 簡介 定義 javascript是一門動態弱類型的解釋型編程語言,增強頁面動態效果,實現頁面與用戶之間的實時動態的交互。 javascript是由三部分組成:ECMAScript、DOM、BOM ECMAScript由ECMA-262定義,提供核 ...
  • ...
  • 1.解決 瀏覽器 返回按鈕不刷新的問題 window.onpageshow = function(event) { if (event.persisted) { window.location.reload() }};2.H5 中 JS 禁用安卓手機物理返回鍵 XBack = {}; (functi ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...