現(xiàn)代應(yīng)用程序要求高性能和響應(yīng)性,這要求開發(fā)者掌握并發(fā)和并行。TypeScript 作為 JavaScript 的超集,提供了強大的工具和模式來管理這些復(fù)雜性。本指南從各個角度探討這兩個概念,深入實際示例、模式和高級實踐,以利用 TypeScript 中的并發(fā)和并行。
并發(fā)與并行:關(guān)鍵區(qū)別
在深入代碼之前,理解這些術(shù)語至關(guān)重要:
1.并發(fā):
- 定義:系統(tǒng)通過交錯執(zhí)行多個任務(wù)的能力(不一定是同時進(jìn)行)。
- 示例:在事件循環(huán)中切換處理數(shù)據(jù)庫查詢和文件上傳。
2.并行:
- 定義:通過利用多核處理器同時執(zhí)行多個任務(wù)。
- 示例:在不同的核心上同時進(jìn)行復(fù)雜的數(shù)學(xué)計算。
可視化:
想象一個餐廳:
- 并發(fā):一個廚師在多個菜肴之間多任務(wù)處理。
TypeScript 中的并發(fā)
JavaScript,以及擴(kuò)展的 TypeScript,運行在單線程事件循環(huán)上,這可能使得并發(fā)聽起來不可能實現(xiàn)。然而,通過異步編程模型如回調(diào)、承諾和async/await實現(xiàn)了并發(fā)。
1. 使用 Promise 實現(xiàn)并發(fā)
Promises 是在 TypeScript 中實現(xiàn)并發(fā)的最簡單方式之一。
const fetchData = (url: string) => {
returnnewPromise<string>((resolve) => {
setTimeout(() => resolve(`Data from ${url}`), 1000);
});
};
const main = async () => {
console.log('Fetching data concurrently...');
const data1 = fetchData('https://api.example.com/1');
const data2 = fetchData('https://api.example.com/2');
const results = awaitPromise.all([data1, data2]);
console.log(results); // ["Data from https://api.example.com/1", "Data from https://api.example.com/2"]
};
main();
解釋:
Promise.all
允許兩個獲取操作并發(fā)運行,節(jié)省時間。
2. 使用 Async/Await 實現(xiàn)并發(fā)
async/await
在保持異步特性的同時簡化了 promise 鏈。
async function task1() {
console.log("Task 1 started");
awaitnewPromise((resolve) => setTimeout(resolve, 2000));
console.log("Task 1 completed");
}
asyncfunction task2() {
console.log("Task 2 started");
awaitnewPromise((resolve) => setTimeout(resolve, 1000));
console.log("Task 2 completed");
}
asyncfunction main() {
console.log("Concurrent execution...");
awaitPromise.all([task1(), task2()]);
console.log("All tasks completed");
}
main();
TypeScript 中的并行
雖然 JavaScript 本身不支持多線程,但 Web Workers 和 Node.js Worker Threads 啟用了并行。這些特性利用單獨的線程來處理計算密集型任務(wù)。
1. Web Workers 實現(xiàn)并行
在瀏覽器環(huán)境中,Web Workers 在單獨的線程中執(zhí)行腳本。
// worker.ts
addEventListener('message', (event) => {
const result = event.data.map((num: number) => num * 2);
postMessage(result);
});
// main.ts
const worker = new Worker('worker.js');
worker.onmessage = (event) => {
console.log('Result from worker:', event.data);
};
worker.postMessage([1, 2, 3, 4]);
2. Node.js Worker Threads 實現(xiàn)并行
對于服務(wù)器端應(yīng)用程序,Node.js 提供了worker_threads
。
// worker.js
const { parentPort } = require('worker_threads');
parentPort.on('message', (data) => {
const result = data.map((num) => num * 2);
parentPort.postMessage(result);
});
// main.js
const { Worker } = require('worker_threads');
const worker = new Worker('./worker.js');
worker.on('message', (result) => {
console.log('Worker result:', result);
});
worker.postMessage([1, 2, 3, 4]);
有效并發(fā)與并行的模式
1. 任務(wù)隊列管理并發(fā)
在處理許多任務(wù)時,任務(wù)隊列確保受控執(zhí)行。
class TaskQueue {
private queue: (() =>Promise<void>)[] = [];
private running = 0;
constructor(private concurrencyLimit: number) {}
enqueue(task: () =>Promise<void>) {
this.queue.push(task);
this.run();
}
private async run() {
if (this.running >= this.concurrencyLimit || this.queue.length === 0) return;
this.running++;
const task = this.queue.shift();
if (task) await task();
this.running--;
this.run();
}
}
// 使用
const queue = new TaskQueue(3);
for (let i = 0; i < 10; i++) {
queue.enqueue(async () => {
console.log(`Task ${i} started`);
awaitnewPromise((resolve) => setTimeout(resolve, 1000));
console.log(`Task ${i} completed`);
});
}
2. 使用工作池進(jìn)行負(fù)載均衡
工作池高效地在多個工作線程之間分配任務(wù)。
import { Worker, isMainThread, parentPort, workerData } from'worker_threads';
if (isMainThread) {
const workers = Array.from({ length: 4 }, () => new Worker(__filename));
const tasks = [10, 20, 30, 40];
workers.forEach((worker, index) => {
worker.postMessage(tasks[index]);
worker.on('message', (result) => console.log('Result:', result));
});
} else {
parentPort.on('message', (task) => {
parentPort.postMessage(task * 2);
});
}
挑戰(zhàn)與解決方案
- 使用 Node.js 中的 async_hooks 等工具來追蹤異步操作。
- 使用支持調(diào)試 async/await 代碼的 IDE。
- 將 promise 包裝在 try/catch 塊中,或與 Promise.all 一起使用 .catch()。
并發(fā)與并行的最佳實踐
- 優(yōu)先考慮異步 I/O:避免在 I/O 密集型操作中阻塞主線程。
- 為 CPU 密集型任務(wù)使用工作線程:將重計算卸載到工作線程或 Web Workers。
- 限制并發(fā):使用任務(wù)隊列或 p-limit 等庫來控制并發(fā)級別。
- 利用庫:使用 Bull 等庫進(jìn)行任務(wù)隊列管理,或使用 Workerpool 進(jìn)行工作線程管理。
結(jié)論
并發(fā)和并行對于構(gòu)建高性能、可擴(kuò)展的 TypeScript 應(yīng)用程序至關(guān)重要。并發(fā)通過交錯任務(wù)提高響應(yīng)性,而并行則在多核系統(tǒng)上實現(xiàn)同時執(zhí)行。通過掌握這些概念,開發(fā)者可以應(yīng)對現(xiàn)代應(yīng)用程序中的挑戰(zhàn),并提供無縫的用戶體驗。
?原文地址:https://dev.to/shafayeat/mastering-concurrency-and-parallelism-in-typescript-1bgf
該文章在 2024/12/30 12:41:54 編輯過