掌握 TypeScript 中的并发和并行
现代应用程序需要高性能和响应能力,这要求开发人员掌握并发性和并行性。TypeScript 作为 JavaScript 的超集,提供了强大的工具和模式来管理这些复杂性。本指南从各个角度探讨了这两个概念,深入探讨了在 TypeScript 中利用并发性和并行性的实际示例、模式和高级实践。
并发与并行:主要区别
在开始编写代码之前,理解以下术语至关重要:
**1.并发性:**
**2.并行性:**
**可视化:**
想象一个餐厅:
TypeScript 中的并发
JavaScript 以及 TypeScript 都运行在 **单线程事件循环** 上,这听起来可能让并发变得不可能。然而,并发是通过 **回调**、**承诺** 和 **异步/等待** 等异步编程模型实现的。
**1. 使用 Promises 实现并发**
Promises 是 TypeScript 中实现并发的最简单方法之一。
const fetchData = (url: string) => { return new Promise((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 = await Promise.all([data1, data2]); console.log(results); // ["Data from https://api.example.com/1", "Data from https://api.example.com/2"] }; main();
**解释:**
async function task1() { console.log("Task 1 started"); await new Promise((resolve) => setTimeout(resolve, 2000)); console.log("Task 1 completed"); } async function task2() { console.log("Task 2 started"); await new Promise((resolve) => setTimeout(resolve, 1000)); console.log("Task 2 completed"); } async function main() { console.log("Concurrent execution..."); await Promise.all([task1(), task2()]); console.log("All tasks completed"); } main();
TypeScript 中的并行性
尽管 JavaScript 本身不支持多线程,但 Web Workers 和 Node.js Worker Threads 可以实现并行。这些功能利用单独的线程来处理计算量大的任务。
**1. 用于并行的 Web Worker**
在浏览器环境中,Web Workers 在单独的线程中执行脚本。
// 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 工作线程**
对于服务器端应用程序,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]);
有效并发和并行的模式
**1. 用于管理并发的任务队列**
当处理许多任务时,任务队列可确保受控执行。
class TaskQueue { private queue: (() => Promise)[] = []; private running = 0; constructor(private concurrencyLimit: number) {} enqueue(task: () => Promise ) { 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(); } } // Usage const queue = new TaskQueue(3); for (let i = 0; i < 10; i++) { queue.enqueue(async () => { console.log(`Task ${i} started`); await new Promise((resolve) => setTimeout(resolve, 1000)); console.log(`Task ${i} completed`); }); }
**2. 使用工作池进行负载平衡**
工作池有效地在多个工作器之间分配任务。
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); }); }
挑战与解决方案
**1. 调试异步代码**
**2. 错误处理**
**3. 竞争条件**
避免共享状态或使用锁定机制。
并发和并行的最佳实践
**1. 优先考虑异步 I/O:**避免阻塞主线程进行 I/O 密集型操作。
**2. 使用工作线程执行 CPU 密集型任务:**将繁重的计算任务卸载到工作线程或 Web 工作线程上。
**3. 限制并发**:使用任务队列或类似“p-limit”的库来控制并发级别。
**4. 利用库:**使用像“Bull”这样的库进行任务队列或“Workerpool”进行工作线程管理。
**结论**
并发性和并行性对于构建高性能、可扩展的 TypeScript 应用程序至关重要。并发性通过交错任务来提高响应能力,而并行性则可以在多核系统上同时执行。通过掌握这些概念,开发人员可以应对现代应用程序中的挑战并提供无缝的用户体验。
我的个人网站:https://shafayet.zya.me
这是如何关闭 Vim...😭😭😭
