」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > JavaScript 如何在後台工作:了解其單線程性質和非同步操作

JavaScript 如何在後台工作:了解其單線程性質和非同步操作

發佈於2024-12-22
瀏覽:616

How JavaScript Works in the Background: Understanding Its Single-Threaded Nature and Asynchronous Operations

JavaScript 是網路的支柱,為數十億網站和應用程式提供動態用戶端功能。但您有沒有想過 JavaScript 是如何在後台發揮魔力的?在這篇文章中,我們將深入研究 JavaScript 單線程本質的內部工作原理並探索非同步程式設計的概念。

單線程是什麼意思?

當我們說 JavaScript 是「單線程」時,這意味著它有一個呼叫堆疊。呼叫堆疊本質上是 JavaScript 追蹤正在執行的函數的結構。它遵循後進先出 (LIFO) 順序,這意味著最後推送到堆疊的函數將最先完成。以下是其工作原理的範例:

function first() {
    console.log('First function');
}

function second() {
    console.log('Second function');
}

first();
second();

在本例中,first()函數被加入到堆疊並執行。一旦完成,它就會被彈出,第二個()函數被壓入堆疊並接下來執行。

雖然單線程語言可能看起來有限,因為它們一次只能做一件事,但 JavaScript 巧妙地使用非同步機制使其能夠模擬多任務處理。

事件循環和非同步執行

JavaScript 使用非同步執行來處理可能需要很長時間才能完成的操作,例如網路請求、檔案 I/O 或計時器。儘管是單線程的,但由於事件循環和回調隊列,它可以同時管理多個任務。

事件循環

事件循環是JavaScript並發模型中的核心概念。它的主要職責是管理 JavaScript 如何處理非同步程式碼執行。其運作原理如下:

  1. 同步程式碼首先運行。當 JavaScript 啟動時,它使用呼叫堆疊以同步方式逐行執行全域範圍內的所有程式碼。

  2. 非同步任務被傳送到 Web API(如 setTimeout、fetch 等)或 Node.js API,它們將在後台進行處理。

  3. 回呼佇列是非同步操作完成後放置的地方。

  4. 事件循環不斷檢查呼叫堆疊是否為空。如果堆疊為空,它將從回調佇列中取出第一項並將其推送到呼叫堆疊上,以允許其執行。

非同步 JavaScript 的魔力在於事件循環、呼叫堆疊和回呼佇列之間的交互作用。非同步操作不會阻塞呼叫堆疊,這意味著 JavaScript 可以在等待後台任務完成的同時繼續執行其他程式碼。

範例:使用 setTimeout

考慮以下帶有 setTimeout 函數的範例:

console.log('Start');

setTimeout(() => {
    console.log('This runs after 2 seconds');
}, 2000);

console.log('End');

這是一步一步發生的事情:

  1. JavaScript 列印「Start」。

  2. setTimeout 函數被調用,但不是阻塞執行 2 秒,而是發送到 Web API,在後台運行。

  3. JavaScript 列印“End”,繼續執行而不等待 setTimeout 完成。

  4. 2秒後,setTimeout內部的回呼函數放入回呼佇列中。

  5. 事件循環檢查呼叫堆疊是否為空(確實如此),然後將回調函數推入堆疊並執行它,列印「This running after 2秒」。

Promise 和非同步/等待

現代JavaScript 中處理非同步任務的另一種流行方法是透過Promises 和async/await 語法,這有助於透過避免深層嵌套的回呼(也稱為「回調地獄」)來提高程式碼的可讀性。

Promise 表示非同步操作的最終完成(或失敗)及其結果值。這是一個例子:

const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('Promise resolved!');
    }, 1000);
});

promise.then(result => {
    console.log(result);  // Output after 1 second: 'Promise resolved!'
});

我們可以使用 then() 來處理 Promise 解決時發生的情況,而不是依賴回調。如果我們想以更同步的方式處理非同步程式碼,我們可以使用 async/await:

async function asyncExample() {
    const result = await promise;
    console.log(result);  // Output after 1 second: 'Promise resolved!'
}

asyncExample();

這使得程式碼更清晰、更容易理解,讓我們在移動到下一行程式碼之前「等待」非同步任務完成,即使 JavaScript 在幕後仍然是非阻塞的。

JavaScript 非同步模型中的關鍵元件

  1. 呼叫堆疊:執行同步程式碼的地方。

  2. Web API/Node.js API:處理非同步任務(如網路請求)的外部環境。

  3. 回呼佇列:非同步任務結果等待推送到呼叫堆疊執行的佇列。

  4. 事件循環:在呼叫堆疊和回調佇列之間進行協調的系統,確保任務以正確的順序處理。

結論

JavaScript 的單執行緒特性乍看之下似乎有局限性,但其非同步功能使其能夠有效地管理多個任務。透過事件循環、回呼佇列和 Promises 等機制,JavaScript 能夠處理複雜的非阻塞操作,同時保持直覺、同步的程式設計風格。

版本聲明 本文轉載於:https://dev.to/saiarlen/how-javascript-works-in-the-background-understanding-its-single-threaded-nature-and-asynchronous-operations-5be4?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta:列偏移的刪除和恢復Bootstrap 4 在其Beta 1 版本中引入了重大更改柱子偏移了。然而,隨著 Beta 2 的後續發布,這些變化已經逆轉。 從 offset-md-* 到 ml-auto在 Bootstrap 4 Beta 1 中, offset-md-*...
    程式設計 發佈於2024-12-23
  • 儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    解決PHP 中的POST 請求故障在提供的程式碼片段中:action=''而非:action="<?php echo $_SERVER['PHP_SELF'];?>";?>"檢查$_POST陣列:表單提交後使用 var_dump 檢查 $_POST 陣列的內...
    程式設計 發佈於2024-12-23
  • 插入資料時如何修復「常規錯誤:2006 MySQL 伺服器已消失」?
    插入資料時如何修復「常規錯誤:2006 MySQL 伺服器已消失」?
    插入記錄時如何解決「一般錯誤:2006 MySQL 伺服器已消失」介紹:將資料插入MySQL 資料庫有時會導致錯誤「一般錯誤:2006 MySQL 伺服器已消失」。當與伺服器的連線遺失時會出現此錯誤,通常是由於 MySQL 配置中的兩個變數之一所致。 解決方案:解決此錯誤的關鍵是調整wait_tim...
    程式設計 發佈於2024-12-23
  • Go可以存取初始標準輸入流嗎?
    Go可以存取初始標準輸入流嗎?
    在 Go 中,您可以存取初始標準輸入嗎? 在 Go 中,使用 os.Stdin 從原始標準輸入讀取應該會產生所需的結果,如圖所示通過這個代碼片段:package main import "os" import "log" import "io&quo...
    程式設計 發佈於2024-12-23
  • 大批
    大批
    方法是可以在物件上呼叫的 fns 數組是對象,因此它們在 JS 中也有方法。 slice(begin):將陣列的一部分提取到新數組中,而不改變原始數組。 let arr = ['a','b','c','d','e']; // Usecase: Extract till index ...
    程式設計 發佈於2024-12-23
  • 如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    在 PHP 中組合關聯數組在 PHP 中,將兩個關聯數組組合成一個數組是常見任務。考慮以下請求:問題描述:提供的代碼定義了兩個關聯數組,$array1 和 $array2。目標是建立一個新陣列 $array3,它合併兩個陣列中的所有鍵值對。 此外,提供的陣列具有唯一的 ID,而名稱可能重疊。要求是建...
    程式設計 發佈於2024-12-23
  • 極簡密碼管理器桌面應用程式:進軍 Golang 的 Wails 框架(第 2 部分)
    極簡密碼管理器桌面應用程式:進軍 Golang 的 Wails 框架(第 2 部分)
    Hi again, coders! In the first part of this short series we saw the creation and operation of a desktop application to store and encrypt our passwords...
    程式設計 發佈於2024-12-23
  • ES6 React 元件:何時使用基於類別與函數式?
    ES6 React 元件:何時使用基於類別與函數式?
    在ES6 基於類別和函數式ES6 React 元件之間做出選擇使用React 時,開發人員面臨著使用ES6 基於類別的選擇組件或功能ES6 組件。了解每種類型的適當用例對於最佳應用程式開發至關重要。 函數式 ES6 元件:無狀態且簡單函數式元件是無狀態的,這表示它們不維護任何內部狀態。他們只是接收道...
    程式設計 發佈於2024-12-23
  • 如何在 PHP 中找到兩個平面數組之間的唯一值?
    如何在 PHP 中找到兩個平面數組之間的唯一值?
    在平面數組之間查找唯一值給定兩個數組,任務是確定僅存在於其中一個數組中的值。此操作通常稱為尋找兩個集合之間的差異。 在 PHP 中,您可以利用 array_merge、array_diff 和 array_diff 函數來實現此操作。詳細解法如下:$array1 = [64, 98, 112, 92...
    程式設計 發佈於2024-12-23
  • 在 Go 中使用 WebSocket 進行即時通信
    在 Go 中使用 WebSocket 進行即時通信
    构建需要实时更新的应用程序(例如聊天应用程序、实时通知或协作工具)需要一种比传统 HTTP 更快、更具交互性的通信方法。这就是 WebSockets 发挥作用的地方!今天,我们将探讨如何在 Go 中使用 WebSocket,以便您可以向应用程序添加实时功能。 在这篇文章中,我们将介绍: WebSoc...
    程式設計 發佈於2024-12-23
  • CSS 可以在內聯區塊元素中本機插入換行符號嗎?
    CSS 可以在內聯區塊元素中本機插入換行符號嗎?
    CSS 在行內區塊元素中插入換行符:理論探索在不斷發展的Web 開發領域,這種能力操縱內容流仍然是最重要的。經常出現的一個特殊挑戰涉及在內聯區塊元素中插入換行符。 考慮以下 HTML 結構:<h3 id="features">Features</h3> &...
    程式設計 發佈於2024-12-23
  • 如何在 PHP 中輕鬆轉換時區之間的時間和日期?
    如何在 PHP 中輕鬆轉換時區之間的時間和日期?
    在PHP 中轉換時區之間的時間和日期使用PHP,您可以輕鬆地在不同時區之間轉換時間和日期。此功能在處理全球資料的應用程式或與來自不同位置的使用者一起工作時特別有用。 取得時區偏移量要取得與 GMT 的時間偏移量,您可以使用 DateTimeZone 類別。它提供了時區及其各自偏移量的完整清單。 $t...
    程式設計 發佈於2024-12-23
  • HTML 格式標籤
    HTML 格式標籤
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    程式設計 發佈於2024-12-23
  • 如何在Windows上安裝並使用Pip進行Python套件管理?
    如何在Windows上安裝並使用Pip進行Python套件管理?
    Pip:在Windows 上安裝Python 套件的輕鬆方式在Windows 上安裝Python 套件可能是一項艱鉅的任務,特別是如果您在使用EasyInstall 時遇到困難。幸運的是,EasyInstall 的後繼者 Pip 提供了更簡化和簡化的解決方案。 在Windows 上逐步安裝Pip若要...
    程式設計 發佈於2024-12-23
  • 如何在Python的`type()`和`isinstance()`之間進行選擇以進行物件類型檢查?
    如何在Python的`type()`和`isinstance()`之間進行選擇以進行物件類型檢查?
    如何確定物件的類型確定物件的類型對於保證資料一致性並相應地執行操作至關重要。 Python 為此目的提供了兩個內建函數:type() 和 isinstance()。 使用 type()type() 函數傳回確切的型別一個物件的。例如:>>> type([]) is list Tru...
    程式設計 發佈於2024-12-23

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3