iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
0
自我挑戰組

玩轉 React 從0到1系列 第 9

【Day 9】關於ES6 的 同步與異步

前言

關於這一章我們會花時間定義一下 JS 的同步和非同步,簡介一下 JS 這語言的特性與跟瀏覽器的關係。雖然可能會覺得主題有點跳,但是像是 JS 相關的渲染效果或是執行順序,以及下兩章節要講的 Promise 跟 async/await都與它習習相關。

Javascript 這語言本身就設計為單線程,因為作為瀏覽器的腳本而言,它主要負責的頁面的互動,以及Dom的操作,所以它只能是單線程,否則會導致很多問題,例如:一個線程要進行渲染特效,但另一個線程卻要刪除這個節點,瀏覽器這時候該怎麼反應?

所以為了避免這種問題,Javascript 就是單線程,而這裡指的單線程是說 Javascript 解析跟執行代碼的線程只有一個,而瀏覽器是多線程的與 Javascript 單線程並不衝突,因為瀏覽器只是 Javascript 的運行環境。

進程(Process) 與 線程(Thread)

什麼是進程(Process) ?

可以將工作管理員打開,這時後你會看到許多執行應用程式,每個應用程式或許命名為 ****.exe。是的,可以把每一個 ****.exe 都當作一個進程來看待。

什麼是線程(Thread)?

那 ****.exe 中可能會做很多事,像是瀏覽器,當你點擊它的時候,它幫你開網頁;當你不知不覺,它就幫你更新好了你有安裝的相關套件的最新版,可以把它們各自都當作是一個線程來看待。

線程(Thread)與進程(Process)的關係?

進程擁有自己的系統資源,而且互相不影響,所以如果一個進程 crash 掉並不會對其他的進程造成影響。線程則是由進程堆疊起來的,所以當線程 crash 掉了,所有的進程也會跟著 crash。
也因此多進程的程序是比多線程的程序健康的,但是進程在切換時,耗費資源會較多,效率會比較差。

如何看待同步?

所謂的同步,就是做完一件事才能做下一件事

let num = [];
for(let i = 0;i < 100;i++){
    num[i] = i;
}
console.log(num);

上面這段代碼是由上到下依順序執行,最後才會輸出,而這就是同步,事實上大部分程式還是同步多。

如何看待異步?

在做一件事情時,因為這件事會花費很長時間,所以在做這件事的同時,你還可以去處理其他事情。

由於瀏覽器是多線程的,但解析 Javascript 的程式卻是單線程的,所以有些任務需要耗費時間(像是 ajax, loading),如果按照同步的方式就會阻塞。所以單線程中有一些任務需要耗費時間,就把這些事情通過新開的線程來實現,而瀏覽器會針對那些耗時間的任務,會開一個新的進程單獨去處理。

Javascript 執行機制

  1. 先執行主線程的同步任務
  2. 異步任務 (Callback) 放入對應的異步進程處理,然後推入堆疊中
  3. 一旦主線程中所有的同步任務執行完畢,系統會依序讀取堆疊中的異步任務,於是被讀取的異步任務結束等待狀態,開始執行。

https://ithelp.ithome.com.tw/upload/images/20200925/20109963elOgOdxJSx.png

說到這裡,所以 Javascript 的單線程又是如何實現異步?就是依據上圖的事件循環 (event loop) 實現。

舉個例子,可以猜猜下面的解是多少?

console.log('1');
setTimeout(function(){
    console.log('2');
},0);
console.log('3');
// 1,3,2

setTimeout 會在堆疊中添加一個元素,而 0 作為第二個參數被傳入,如果堆疊中沒有其他元素,元素會被立刻處理。但是,如果主線程有其他的元素,setTimeout必須等其他元素處理完,因此第二個參數僅僅表示最少的時間,而不是確切的時間。

同步 vs 異步

同步任務可以保證順序一致性,代碼也比較好理解,但卻容易造成阻塞;異步任務可以解決阻塞的問題,但卻會改變了順序,所以需要根據需求去撰寫程式。

後續我們會介紹 Javascript 處理異步的方式,ES6 的 Promise 以及 ES7 的 async/await。

結論

  • 介紹了 同步 與 非同步(異步)

/images/emoticon/emoticon33.gif


上一篇
【Day 8】關於ES6 關鍵字 this
下一篇
【Day 10】關於ES6 的 Promise
系列文
玩轉 React 從0到130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言