node基礎(1)---eventloop事件環

好想吃涼皮發表於2018-04-06

##在瀏覽器中,全域性作用域是window,而在node中是global。

但是我們可以直接var a=1;console.log(window.a),但是我們不能console.log(global.a),因為node在執行的時候會形成一個閉包來實現模組化。

node解決了什麼

Node的首要目標是提供一種簡單的,用於建立高效能伺服器的開發工具
Web伺服器的瓶頸在於併發的使用者量,對比Java和Php的實現方式

Node在處理高併發,I/O密集場景有明顯的效能優勢

  • 高併發,是指在同一時間併發訪問伺服器
  • I/O密集指的是檔案操作、網路操作、資料庫,相對的有CPU密集,CPU密集指的是邏輯處理運算、壓縮、解壓、加密、解密

Web主要場景就是接收客戶端的請求讀取靜態資源和渲染介面,所以Node非常適合Web應用的開發。

Console

在Node.js中,使用console物件代表控制檯(在作業系統中表現為一個作業系統指定的字元介面,比如 Window中的命令提示視窗),一下列出一些基本用法:

  • console.log (標準輸出
  • console.info(標準輸出
  • console.error(錯誤輸出
  • console.warn (錯誤輸出
  • console.dir (
    console.dir(Array.prototype,{showHidden:true})
  • console.time
  • console.timeEnd
  • console.trace
  • console.assert (斷言
    console.assert((1+1==3),'error')

執行緒和程式

執行緒,有時被稱為輕量級程式(Lightweight Process,LWP),是程式執行流的最小單元。執行緒是程式中的一個實體,是被系統獨立排程和分派的基本單位,執行緒自己不擁有系統資源,只擁有一點兒在執行中必不可少的資源,但它可與同屬一個 程式的其它執行緒共享程式所擁有的全部資源。一個執行緒可以建立和撤消另一個執行緒,同一程式中的多個執行緒之間可以併發執行。由於執行緒之間的相互制約,致使執行緒 在執行中呈現出間斷性。執行緒也有就緒阻塞執行三種基本狀態。就緒狀態是指執行緒具備執行的所有條件,邏輯上可以執行,在等待處理機;執行狀態是指執行緒佔有處理機正在執行;阻塞狀態是指執行緒在等待一個事件(如某個訊號量),邏輯上不可執行。每一個程式都至少有一個執行緒,若程式只有一個執行緒,那就是程式本身。

多執行緒靠的是切換時間片,這個過程中可能會浪費資源;計算在分配資源時,按照程式為單位。而node 中是單執行緒(主執行緒),並且是非同步非阻塞的。

談談瀏覽器

node基礎(1)---eventloop事件環

  • 使用者介面-包括位址列、前進/後退按鈕、書籤選單等
  • 瀏覽器引擎-在使用者介面和呈現引擎之間傳送指令(瀏覽器的主程式)
  • 渲染引擎,也被稱為瀏覽器核心(瀏覽器渲染程式)
  • 一個外掛對應一個程式(第三方外掛程式)
  • GPU提高網頁瀏覽的體驗(GPU程式)

由此可見瀏覽器是多程式的,並且從我們的角度來看我們更加關心瀏覽器渲染引擎

其他執行緒 #

  • 瀏覽器事件觸發執行緒(用來控制事件迴圈,存放setTimeout、瀏覽器事件、ajax的回撥函式)
  • 定時觸發器執行緒(setTimeout定時器所線上程)
  • 非同步HTTP請求執行緒(ajax請求執行緒)

單執行緒特點是節約了記憶體,並且不需要在切換執行上下文。而且單執行緒不需要管鎖的問題,這裡簡單說下鎖的概念。例如下課了大家都要去上廁所,廁所就一個,相當於所有人都要訪問同一個資源。那麼先進去的就要上鎖。而對於node來說。下課了就一個人去廁所,所以免除了鎖的問題!

node基礎(1)---eventloop事件環

瀏覽器的事件環是先執行微任務再執行巨集任務,但是這裡面有個程式碼編譯的時間線,不會把佇列裡的都執行完。(跟node不同)

為了方便理解執行棧的概念我們看個例子

function one(){
    let a = 1;
    two();
    function two(){
        let b = 2;
        three();
        function three(){
            console.trace()
            console.log(b)
        }
    }
}
one();複製程式碼

node基礎(1)---eventloop事件環

這個圖就是程式碼執行的時候出來的執行棧(執行過程從下往上)。

·····#####################################

為了方便理解巨集任務和微任務的執行順序我們也來一個例子:

console.log(1)
setTimeout(function(){
    console.log(4)
},0)
let promise = new Promise(function(resolve,reject){
    console.log(3)
    resolve(100)
}).then(function(data){
    console.log(100)
    setTimeout(function(){
        console.log(5)
    },0)
})
console.log(2)複製程式碼

控制檯會先輸出13(new Promise的時候就立即執行)2,setTimeout的執行內容放到巨集任務佇列中,then執行內容放微任務中,最後在把輸出5的也方到巨集任務中,因為微任務先於巨集任務執行,那麼輸出結果:

node基礎(1)---eventloop事件環

  • 1.所有同步任務都在主執行緒上執行,形成一個執行棧
  • 2.主執行緒之外,還存在一個任務佇列。只要非同步任務有了執行結果,就在任務佇列之中放置一個事件。
  • 3.一旦執行棧中的所有同步任務執行完畢,系統就會讀取任務佇列,將佇列中的事件放到執行棧中依次執行
  • 4.主執行緒從任務佇列中讀取事件,這個過程是迴圈不斷的

整個的這種執行機制又稱為Event Loop(事件迴圈)

###node系統

我們先來張圖看看node是如何工作的

node基礎(1)---eventloop事件環

  • 1.我們寫的js程式碼會交給v8引擎進行處理
  • 2.程式碼中可能會呼叫nodeApi,node會交給libuv庫處理
  • 3.libuv通過阻塞i/o和多執行緒實現了非同步io
  • 4.通過事件驅動的方式,將結果放到事件佇列中,最終交給我們的應用。

Node中的Event Loop

在libuv內部有這樣一個事件環機制。在node啟動時會初始化事件環

node基礎(1)---eventloop事件環


這裡每一個階段都對應一個事件佇列,當event loop執行到某個階段時會將當前階段對應的佇列依次執行。當佇列執行完畢或者執行的數量超過上線時,會轉入下一個階段。這裡我們重點關注poll階段

node事件環跟瀏覽器的事件環類似唯一不同的是它是把佇列的執行完才執行下個佇列。

舉個例子:

console.log(1);
console.log(2);
setTimeout(function(){
    console.log('setTimeout1')
    Promise.resolve().then(function(){
        console.log('promise')
    });
})
setTimeout(function(){
    console.log('setTimeout2');
});複製程式碼
這個用瀏覽器控制檯和vscode執行出來的不一樣,自己可以執行一下哦。










單執行緒特點是節約了記憶體,並且不需要在切換執行上下文。而且單執行緒不需要管鎖的問題,這裡簡單說下鎖的概念。例如下課了大家都要去上廁所,廁所就一個,相當於所有人都要訪問同一個資源。那麼先進去的就要上鎖。而對於node來說。下課了就一個人去廁所,所以免除了鎖的問題!


相關文章