avatar

認識process與thread之前,首先要先認識同步與非同步的演變

同步/非同步

同步

一次做一件事情,JavaScript是單一執行緒,因此只會在同一時間執行一個task。
現在有以下的程式,會逐漸的放入callstack,再pop出來執行:

1
2
3
4
5
6
7
8
9
const second = () => {
console.log('Second');
}
const first = () => {
console.log('First');
second();
console.log('Over');
}
first();

不過同步有個問題是,如果中間有一大坨東西卡住,是不是就動不了了?

1
2
3
console.log('1');
while(true); // Blocking
console.log('2');

看起來很困繞對吧?必須要等到中間的任務完成(或是根本無法完成)才能繼續執行下面的程式。

非同步

解決同步問題的方式就是使用asynchronous callbacks,透過event loop解決單一執行序的困擾,達成非同步的效果。
事實上在開發的過程就有用到很多非同步的功能了,例如:API request, web API, document…

V8 engine

在過去JavaScript都是直譯執行的,但是在V8 engine出現後,結合混合編譯與直譯的方式執行程式(Just In Time),讓JavaScript提升大量的效能。至於V8的執行方式又是另一個世界了,不過大概可以整理出幾個重點:

  1. engine主要包含memory heap,包含宣告的variable與function。callstack,用來放置可執行的單位。
  2. setTimeout之類的web API並不包含在engine內
  3. 透過web API可以callback function
  4. 一旦callstack空了,會夠過Event loop推送Event Queue到callstack執行

callback原理

假設你希望程式先執行getUser再執行storeUser。

1
2
3
4
function example() {
getUser(); // call API
storeUser();
}

但是需要等待getUser拿到資料才可以儲存資料呀,所以可以寫成callback:

1
2
3
4
5
function example() {
getUser(function(data) {
storeUser(data);
});
}

如果你了解event loop原理的話,example會先丟入callstack產生callback,執行完再丟入getUser。
但是這樣的程式碼很容易讓人混淆,不好維護。

Job Queue/Micro task - ES6

ES6推出Promise之後,解決了非同步需要撰寫大量的callback的狀況,Job Queue也隨之出現了,跟以前的Message Queue不同的地方在於,Job Queue的優先權較高,但是為了統一稱呼,我們都會叫做Event Queue。
以下是Promise非同步範例:

1
2
3
4
5
6
function example() {
getUser()
.then(function(res) {
return storeUser(res.payload.data);
});
};

儘管不用寫很深的callback hell,但是換來的是有不斷地then出現…

async/await - ES7

在ES7的Promise出了非同步的Sugar,它的出現讓程式碼更簡潔,真的是拯救蒼生了呀。

1
2
3
4
async function example() {
const data = await getUser();
storeUser(data);
};

Nodejs特色

  1. 不會阻塞 non-blocking
  2. 事件驅動 Event-driven
  3. 資料密集 - data intensive
  4. I/O密集 - I/O intensive

Nodejs是單執行緒在執行,它並不會等待其他事件做完再繼續執行,他會不斷的執行接下來的任務,不會blocking。
儘管程式執行到event的程式碼,但是事件觸發才會真正的執行,這就像JS的Bubbling和Capturing一樣,事件發生而驅動事件。

假設有十個使用者連線Server,其中一位使用者想要抓取一個很大件的資料,如果卡在這位使用者身上,那麼其他9位就別想使用服務了對吧?但是Nodejs並不會影響到其他9位使用者,一樣會正常的給予response。

Nodejs不擅長

  1. 資料計算
  2. Processor intensive
  3. blocking operation

參考

https://ithelp.ithome.com.tw/articles/10191970


Comment