【JS上課筆記】非同步(asynchronous)VS. 同步(synchronous)


Posted by Annie-Chien on 2022-07-26

這一系列的文章為修習 Udemy 的 The Complete JavaScript Course 2022: From Zero to Expert! 這堂課時所做的筆記。


認識「非同步(asynchronous)」之前,先來認識什麼是「同步(synchronous)」。

同步(synchronous)

當我們說程式碼為同步(synchronous)時,指的是它會「逐行」執行。所以,當其中一行程式碼所需的執行時間比較長,那就會導致後面所有的程式碼都要等待它執行完畢才能接續執行,造成「阻塞(blocking)」。

例如:alert() 會產生彈跳視窗,而在使用者還沒按下關閉鈕前,無法繼續執行後面的程式碼。

這概念有點像是,公共廁所只有一間時,長長人龍在廁所外等待的慘況。無論再怎麼急,都得耐心等候廁所裡面的人出來,下一個人才能進去,對吧?

同步聽起來好像有點糟欸(內急憋不住啊...),該怎麼解決 blocking 的問題呢?交給「非同步(asynchronous)」來處理!

非同步(asynchronous)

與同步的概念相反,非同步程式碼不會等待前一行程式碼執行完成才繼續往下執行。例如:

console.log("1: start");
setTimeout(() => {
  console.log("2: timer");
}, 3000);
console.log("3: end");
  • 如果按照我們前面介紹的同步觀念來思考的話,預想這段程式碼的執行結果會是這樣:
    1: start
    2: timer
    3: end
  • 但實際結果是這樣的:
    1: start
    3: end
    2: timer

驚不驚訝啊~所以我們會說 setTimeout() 是「非同步」的任務。

. . .

你在說什麼我聽不懂 一下說JS裡面有同步,一下又說它也有非同步 @@

所以,JS到底是屬於同步還是非同步啦?

簡單一句話,JS是具有「同步」性質的程式語言,但在瀏覽器的協助下,它可以達到非同步的效果。

我們都知道JS是單執行緒(single-threaded)的程式語言,也就是一次只能做一件事情(廁所只有一間,請好好排隊),不過在瀏覽器裡的 JS 有了 web API 的協助,便可以把「非同步」任務丟給 web API 協助處理(太好了!新建了一間廁所),JS 引擎就可以繼續執行自己該做的事情啦。

我們再來重新看看這段程式碼,說故事囉:

console.log("1: start");
setTimeout(() => {
  console.log("2: timer");
}, 3000);
console.log("3: end");

JS 引擎開始從頭逐行執行程式碼...

  1. 首先遇到了console.log("1: start")。OK我處理!印出 1: start。
  2. 再來碰到了setTimeout(...)。欸欸欸這是 web API 的工作啊,我丟!
  3. web API 正在處理setTimeout(...)
  4. 好忙好忙我繼續工作,碰到console.log("3: end")。OK我處理!印出 3: end。
  5. web API 處理完setTimeout(...)後,把裡面由 JS 負責的console.log("2: timer")丟回去給 JS 引擎。
  6. 印出 2: timer。

非同步可以提升執行效率,解決 blocking 的問題!

想想嘛,如果一切都是同步進行,那麼像是載入資料這類需要耗費較多時間的任務,將會導致blocking。使用者可能每執行一個動作,就要等個好幾秒(等到資料成功載入後)才能繼續下個動作。肯定會氣炸的吧 💢

結論

請善加利用非同步(都給你了這個酷法寶還不用嗎!),像是透過 Ajax 來完成非同步請求就能解決載入資料時造成 blocking 的問題。

欸... 可是要怎麼用?😅

下集待續。


#javascript #asychronous







Related Posts

D29_第三週作業

D29_第三週作業

OOP 13 - Dependency Inversion Principle

OOP 13 - Dependency Inversion Principle

後端好朋友 Express 基本介紹與操作

後端好朋友 Express 基本介紹與操作


Comments