Blocking vs Non-Blocking

February 29, 2024

  • concept
  • javascript
有任何問題,我能幫上忙的話都能到 github 發 issue 問我。

Preface

阻塞(blocking),是指在作業系統(operation system,簡稱 OS)中,當系統等待操作完成,接著才允許程式碼繼續執行,用戶在此等待期間無法執行其他任務;相反,非阻塞(non blocking),則是允許執行緒繼續執行,無需等待該操作完成,不會影響其他進程。

Asynchronous programming

在 JavaScript 中,異步是很重要的一個概念,為何說他重要,各位可以試想一下,如果 network request 也就是我們常說的 call API 的這行為是阻塞的,執行完一個才執行下一個,而不是在執行時平行去跟後台要檔案,一隻 API 一秒,十隻 API 就十秒,使用者使用的體感及實際效能是不是會相當的差。

所以我們可以說 JavaSciprt 是一個 Asynchronous Programming Language,但異步的程式語言也就意味著,會有很多 callback (回調函式),如果 API 的邏輯很複雜,就有可能會產生所謂的 callback hell (回調函式地獄),如下方程式碼。

asyncFunction1(param1, function (result1) {
  asyncFunction2(result1, function (result2) {
    asyncFunction3(result2, function (result3) {
      asyncFunction4(result3, function (result4) {
        // Nested callback continues...
      })
    })
  })
})

程式碼會一層一層的非常的深,那要如何緩解這一現象呢?

Promise or Async/Await

使用 Promise 後我們的程式碼會像

asyncFunction1(param1)
  .then(result1 => asyncFunction2(result1))
  .then(result2 => asyncFunction3(result2))
  .then(result3 => asyncFunction4(result3))
  .then(result4 => {
    // Handle final result
  })
  .catch(error => {
    // Handle any errors
  })

而使用 async/await 後我們程式碼會像

try {
  const result1 = await asyncFunction1(param1)
  const result2 = await asyncFunction2(result1)
  const result3 = await asyncFunction3(result2)
  const result4 = await asyncFunction4(result3)
  // Handle final result
} catch (error) {
  // Handle any errors
}

基本上 async/await 這語法糖是建立在 Promise 上,讓我們有種寫起來跟讀起來很像同步 (synchronous) 的程式碼,但事實上並非如此,他並不會造成阻塞,其他程式同時仍會照常執行。

但你或許又有疑問,JavaScript 不是一個單線程語言嗎?在這限制底下,這語言一段時間只能執行一段程式碼,JavaScript 有一個很重要的東西叫做 event loop,基本上執行都是依照這個規則來,簡單來講就是讓程式去排隊,圖示會如下:

image

我個人相當相當建議去看這個 youtube,會對理解這門語言有幫助。

Conclusion

以上是我自己理解的範疇,希望對讀者有幫助,題外話,有興趣可以去看一下 v8 engine,他是 google 寫的 c++ 專案,用來編譯 JavaScript,連結在這


Mayvis Chen
你好,我是 Mayvis Chen
住在台北,會點前端,會點後端,熱愛分享新知及愛喝奶茶的全端打雜工程師。