很多人似乎都無法理解單執行緒NodeJS 是如何與多執行緒後端競爭的。
要找出原因,我們必須了解Nodejs 是單線程的真正意義。
JavaScript 本身最初是為了做一些簡單的事情而創建的,例如驗證表單、做出回應等,直到2009 年,Node.js 的創建者Ryan Dahl 才使使用JavaScript 編寫伺服器端程式碼成為可能。
支援多執行緒的伺服器端語言具有各種結構和構造,用於在執行緒和其他面向執行緒的特性之間同步。
支援這些東西意味著JavaScript 需要改變整個語言,而這也違背了javascript締造者的想法。因此,為了讓純JavaScript 支援多線程,Dahl 必須創建解決方法。讓我們來看看吧!
Node.js 是如何運作的?
Node.js 使用兩種執行緒:由事件循環處理的主執行緒和工作執行緒池的幾個輔助執行緒。
事件循環Node.js 處理非阻塞I/O 操作的機制-儘管JavaScript 是單執行緒處理的-當有可能的時候,它們會把操作轉移到系統核心中去。當JavaScript 操作阻塞執行緒時,事件循環也被阻塞。
工作池是一種執行模型,它產生和處理單獨的線程,然後同步執行任務並將結果傳回事件循環。然後事件循環使用所述結果執行提供的回調。
基本上,工作池處理非同步I/O 操作-主要是與系統磁碟和網路的交互作用。有些模組使用開箱即用的工作池,例如fs(I/O-heavy)或crypto(CPU-heavy)。工作池是在libuv 中實現的,當Node 需要在JavaScript 和C++ 之間內部傳輸資料時,這會導致輕微的延遲,但幾乎可以忽略。
了解事件循環和工作池的意義之後我們看下下面程式碼:
在上面的程式碼中,我們不必同步等待事件。我們將讀取文件的任務委託給工作池,並使用結果呼叫提供的函數。由於工作池有自己的線程,因此事件循環可以在讀取文件的同時繼續正常執行。
跟大家介紹一下:worker_threads
隨著Node.js 10.5.0 的發布,出現了worker_threads。它支援在JavaScript 中建立簡單的多執行緒應用程式
worker_threads 是一個nodejs模組包。線程工作者是在單獨線程中產生的一段程式碼(通常從文件中取出)。
需要注意的是,術語線程工作者、工作者和線程通常可以互換使用。它們都指的是同一件事。
Node.js 中的工作執行緒對於執行繁重的JavaScript 任務很有用。在執行緒的幫助下,Worker 可以輕鬆地並行運行JavaScript 程式碼,使其更快、更有效率。我們可以在不干擾主執行緒的情況下完成繁重的任務。
舊版的Node.js 中沒有引入工作線程。因此,首先更新您的Node.js 以開始使用。
現在建立兩個檔案來實作線程,如下所示:
檔案名稱:worker.js
const { workerData, parentPort } = require('worker_threads'); console.log(`Write-up on how ${workerData} wants to chill with the big boys`); parentPort.postMessage({ filename: workerData, status: 'Done' });
檔名:index.js
const { Worker } = require('worker_threads'); const runSerice = (workerData) => { return new Promise((resolve, reject) => { const worker = new Worker('./worker.js', { workerData }); worker.on('message', resolve); worker.on('error', reject); worker.on('exit', (code) => { if (code !== 0) reject(new Error(`Worker Thread stopped with exit code ${code}`)); }); }); }; const run = async () => { const result = await runSerice('Tunde Ednut'); console.log(result); }; run().catch((err) => console.error(err));
輸出: