TypeScript -- 异步编程

在 TypeScript 中,多线程和异步开发通常是通过 JavaScript 的事件循环和异步编程模型来实现的,因为 JavaScript 是单线程的,但它支持异步操作。TypeScript 作为 JavaScript 的超集,继承了这些特性,并提供了类型系统的支持。以下是在 TypeScript 中进行异步开发的一些常见方法和示例:

Promise

Promise 是 JavaScript 中用于异步编程的一个对象。它代表了一个可能还没有完成的操作的最终结果。

function delay(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}

delay(1000).then(() => {
  console.log('One second has passed!');
});

在这个例子中,delay 函数返回一个 Promise 对象,它将在指定的毫秒数后解决。.then 方法用于指定当 Promise 完成时应该执行的回调函数。

async/await

async/await 是基于 Promise 的另一种编写异步代码的方法,它让异步代码看起来和同步代码类似。

async function fetchData(url: string): Promise<string> {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return await response.text();
  } catch (error) {
    console.error('Fetch error:', error);
  }
}

fetchData('https://api.example.com/data')
  .then(data => console.log(data))
  .catch(error => console.error(error));

在这个例子中,fetchData 函数使用 async 关键字声明,这意味着它的返回值是一个 Promise。在函数体内部,我们使用 await 关键字等待 fetch 操作完成,并获取响应数据。

使用 Web Workers

Web Workers 允许你运行 JavaScript 代码在后台线程中执行,这样可以避免阻塞主线程。

// 创建一个新的 Web Worker
const worker = new Worker('worker.ts');

// 向 Worker 发送消息
worker.postMessage('Hello');

// 接收来自 Worker 的消息
worker.onmessage = (event) => {
  console.log('Message received from worker:', event.data);
};

// worker.ts 文件内容
self.onmessage = (event) => {
  console.log('Message received from main script:', event.data);
  self.postMessage('Worker says hello back!');
};

在这个例子中,我们创建了一个 Worker 实例,并向它发送消息。worker.ts 是 Web Worker 的脚本文件,它在后台线程中运行。

使用 Worker 线程库

由于直接使用 Web Workers 可能需要处理跨域问题和复杂的通信机制,一些库如 comlinkworkly 被开发出来,以简化在 TypeScript 中使用 Web Workers 的过程。

import { Worker } from 'workly';

const worker = new Worker(`export function add(a, b) {
  return a + b;
}`);
worker.add(2, 3).then(result => console.log(result)); // 输出: 5

在这个例子中,我们使用 workly 库创建了一个 Worker,并在其中定义了一个 add 函数。我们可以通过调用 Worker 的方法来执行在 Worker 中定义的函数。

总结

TypeScript 支持多种异步编程模式,包括 Promiseasync/await、Web Workers 和第三方库。这些工具和方法可以帮助你编写非阻塞的、易于维护的异步代码。虽然 JavaScript 是单线程的,但通过这些机制,你可以有效地执行并发操作,提高应用程序的性能和响应性。

Node.js

在 Node.js 中,clusterchild_process 是两个用于处理并发和多任务的模块,它们各自有不同的用途和工作方式。

cluster 模块

cluster 模块是 Node.js 的一个核心模块,它利用操作系统的多进程能力,允许你创建多个工作进程(workers),这些工作进程可以共享服务器端口,形成一个集群(cluster),以实现负载均衡和处理更多的并发连接。

主要特点

  • 每个工作进程都是 Node.js 的一个新实例,拥有自己独立的 V8 引擎和内存空间。
  • 工作进程之间通过 IPC(进程间通信)进行通信。
  • cluster 模块可以自动处理请求的分配,或者你可以自定义请求的分配逻辑。
  • 它特别适用于 I/O 密集型任务的负载均衡,如 Web 服务器或 API 服务。

示例

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  // Fork workers.
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`);
  });
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Hello from worker ' + cluster.worker.id);
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

在这个例子中,主进程(Master)负责创建和监控工作进程(Workers),而每个工作进程都运行一个 HTTP 服务器,监听 8000 端口。

child_process 模块

child_process 模块允许你 spawn(生成)子进程,并与它们进行通信。你可以使用这个模块来运行 shell 命令、执行其他程序,或者创建新的 Node.js 进程。

主要特点

  • 支持 spawnexec 两种方式来生成子进程。
  • spawn 用于生成新进程并与之通信,适合实时交互的场景。
  • exec 用于执行 shell 命令或可执行文件,并在命令执行完毕后获取结果。
  • 子进程可以是同步或异步的,可以传递数据给父进程。

示例

const { spawn } = require('child_process');

// Spawning a shell command
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

在这个例子中,我们使用 spawn 方法生成了一个子进程来执行 ls 命令,并监听子进程的标准输出和标准错误输出。

总结

cluster 模块和 child_process 模块都是 Node.js 中处理并发和多任务的重要工具。cluster 模块更适合于 I/O 密集型任务和 Web 服务场景,它通过创建多个工作进程来实现负载均衡。而 child_process 模块则提供了更通用的子进程管理能力,适用于需要执行外部命令或程序的场景。根据你的应用需求,你可以选择合适的模块来实现并行处理和任务分发。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容