LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

TypeScript 中的并发与并行有什么区别?

admin
2024年12月29日 8:18 本文热度 53

现代应用程序要求高性能和响应性,这要求开发者掌握并发和并行。TypeScript 作为 JavaScript 的超集,提供了强大的工具和模式来管理这些复杂性。本指南从各个角度探讨这两个概念,深入实际示例、模式和高级实践,以利用 TypeScript 中的并发和并行。

并发与并行:关键区别

在深入代码之前,理解这些术语至关重要:

1.并发

  • 定义:系统通过交错执行多个任务的能力(不一定是同时进行)。
  • 示例:在事件循环中切换处理数据库查询和文件上传。

2.并行

  • 定义:通过利用多核处理器同时执行多个任务。
  • 示例:在不同的核心上同时进行复杂的数学计算。

可视化

想象一个餐厅:

  • 并发:一个厨师在多个菜肴之间多任务处理。
  • 并行:多个厨师同时处理不同的菜肴。

TypeScript 中的并发

JavaScript,以及扩展的 TypeScript,运行在单线程事件循环上,这可能使得并发听起来不可能实现。然而,通过异步编程模型如回调、承诺async/await实现了并发。

1. 使用 Promise 实现并发

Promises 是在 TypeScript 中实现并发的最简单方式之一。

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 允许两个获取操作并发运行,节省时间。

2. 使用 Async/Await 实现并发

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 启用了并行。这些特性利用单独的线程来处理计算密集型任务。

1. Web Workers 实现并行

在浏览器环境中,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([1234]);

2. Node.js Worker Threads 实现并行

对于服务器端应用程序,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([1234]);

有效并发与并行的模式

1. 任务队列管理并发

在处理许多任务时,任务队列确保受控执行。

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 === 0return;

    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. 使用工作池进行负载均衡

工作池高效地在多个工作线程之间分配任务。

import { Worker, isMainThread, parentPort, workerData } from'worker_threads';

if (isMainThread) {
const workers = Array.from({ length4 }, () => new Worker(__filename));
const tasks = [10203040];
  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. 调试异步代码
    • 使用 Node.js 中的 async_hooks 等工具来追踪异步操作。
    • 使用支持调试 async/await 代码的 IDE。
  2. 错误处理
    • 将 promise 包装在 try/catch 块中,或与 Promise.all 一起使用 .catch()。
  3. 竞态条件
    • 避免共享状态或使用锁定机制。

并发与并行的最佳实践

  1. 优先考虑异步 I/O:避免在 I/O 密集型操作中阻塞主线程。
  2. 为 CPU 密集型任务使用工作线程:将重计算卸载到工作线程或 Web Workers。
  3. 限制并发:使用任务队列或 p-limit 等库来控制并发级别。
  4. 利用库:使用 Bull 等库进行任务队列管理,或使用 Workerpool 进行工作线程管理。

结论

并发和并行对于构建高性能、可扩展的 TypeScript 应用程序至关重要。并发通过交错任务提高响应性,而并行则在多核系统上实现同时执行。通过掌握这些概念,开发者可以应对现代应用程序中的挑战,并提供无缝的用户体验。


原文地址:https://dev.to/shafayeat/mastering-concurrency-and-parallelism-in-typescript-1bgf


该文章在 2024/12/30 12:41:54 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved