Trabalhador Web em TypeScript

Trabalhador Web em TypeScript

Este artigo explica os Trabalhadores Web em TypeScript.

Você pode aprender sobre o conceito de Web Workers e várias dicas de uso com exemplos.

YouTube Video

Trabalhador em TypeScript

Em TypeScript, um Worker é um mecanismo para realizar processamento em segundo plano, separado do thread principal, aproveitando a API de Trabalhadores Web do JavaScript. Isso permite que cálculos pesados e tarefas assíncronas sejam executados sem afetar a operação da interface do usuário.

Um Worker opera em paralelo com o thread principal (thread da interface do usuário) e pode trocar dados entre threads através de mensagens. Mesmo em TypeScript, você pode usar Worker enquanto escreve código com segurança de tipos.

Uso Básico de Trabalhadores

  1. Criando um Trabalhador

    Crie uma instância do Worker e execute o script especificado. Normalmente, o script é definido em um arquivo separado.

  2. Troca de Mensagens

    Envie e receba mensagens entre o thread principal e o thread do Worker usando postMessage e onmessage.

Exemplo: Implementação Básica de um Trabalhador

  1. worker.ts: Script para o Trabalhador
1// worker.ts
2self.onmessage = (event) => {
3    const data = event.data;
4    const result = data.num1 + data.num2;
5    self.postMessage(result); // Return the result to the main thread
6};
  1. main.ts: Script para usar o Trabalhador no Thread Principal
 1// main.ts
 2const worker = new Worker(
 3    new URL('./worker.ts', import.meta.url),
 4    { type: 'module' }
 5);
 6
 7worker.onmessage = (event) => {
 8    console.log("Result from worker:", event.data); // Receive message from the worker
 9};
10
11worker.postMessage({ num1: 10, num2: 20 }); // Send message to the worker
  • Neste exemplo, o worker.ts é executado em uma thread separada, calcula a soma de num1 e num2 e retorna o resultado ao thread principal. O thread principal recebe o resultado e o exibe no console.
  • Quando você especifica type: 'module', o script Worker é interpretado como um módulo ES, permitindo que você use import e export. Isso permite que você gerencie estruturas de módulos sem usar o tradicional importScripts().

Pontos a Considerar ao Usar Trabalhadores em TypeScript

Adicionando Definições de Tipos

Em TypeScript, defina tipos de dados para garantir uma interação segura entre tipos durante o envio e recebimento de mensagens.

 1// Define data types
 2interface WorkerData {
 3    num1: number;
 4    num2: number;
 5}
 6
 7interface WorkerResult {
 8    result: number;
 9}
10
11// worker.ts
12self.onmessage = (event: MessageEvent<WorkerData>) => {
13    const data = event.data;
14    const result = data.num1 + data.num2;
15    const message: WorkerResult = { result };
16    self.postMessage(message); // Send the result in a type-safe manner
17};
18
19// main.ts
20const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
21
22// Type the event from the worker
23worker.onmessage = (event: MessageEvent<WorkerResult>) => {
24  console.log("Result from worker:", event.data); // event.data is number
25};
26
27// Send typed data to the worker
28const message: WorkerData = { num1: 10, num2: 20 };
29worker.postMessage(message);
  • Ao especificar o parâmetro de tipo em MessageEvent, você pode definir claramente o tipo de dados a receber. Isso permite a troca de dados com segurança de tipos.

Configurando Webpack ou Vite

Ao usar Worker no TypeScript, empacotadores como Webpack ou Vite podem ser necessários. Com essas ferramentas, você pode empacotar corretamente o script do Worker e torná-lo disponível a partir do thread principal.

Por exemplo, ao usar Vite, use import.meta.url para importar corretamente o Worker.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
  • Isso garante que o script do Worker empacotado seja carregado corretamente, permitindo o processamento utilizando o Worker.

Considerações para Mensagens e Concorrência

  1. Cópia de Dados

    Ao enviar e receber mensagens entre o thread principal e o thread do Worker, os dados são copiados. Ao lidar com dados complexos como objetos, é necessário considerar a eficiência. Trocar grandes quantidades de dados com frequência pode degradar o desempenho.

  2. Objetos Transferable

    Alguns objetos, como ArrayBuffer, são chamados de objetos Transferable. Objetos Transferable podem ser transferidos para o Worker em vez de serem copiados durante o envio de mensagens. Isso permite evitar a sobrecarga de cópia de dados.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2
3const buffer = new ArrayBuffer(1024);
4worker.postMessage(buffer, [buffer]); // Transfer ownership to the Worker
5
6console.log(buffer.byteLength); // 0 (ownership moved)
  • Ao passar [buffer] como o segundo argumento para worker.postMessage(), o buffer é transferido para o Worker em vez de ser copiado.

  • Depois disso, o buffer na thread principal fica vazio (com byteLength igual a 0) e só pode ser utilizado pelo Worker.

Encerrando um Worker

O Worker deve ser encerrado após o uso para minimizar o consumo de memória. Você pode encerrar um Worker usando o método terminate.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2// ...
3
4worker.terminate(); // Terminate the Worker
  • Este código encerra o Worker usando o método terminate.

Tratamento de Exceções no Worker

Se ocorrer um erro dentro de um Worker, você pode tratá-lo usando o evento onerror.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2
3worker.onerror = (error) => {
4    console.error("Error in Worker:", error.message);
5};
  • Este código captura e trata erros que ocorrem dentro do Worker utilizando o evento onerror.

Resumo

Ao usar Worker no TypeScript, você pode executar tarefas pesadas em segundo plano enquanto mantém o thread principal fluido. Ao utilizar definições de tipo, as trocas de mensagens também podem ser realizadas de forma segura em relação ao tipo. Ao prestar atenção à troca de dados e ao gerenciamento de threads, você pode alcançar melhorias de desempenho e concorrência eficiente.

Você pode acompanhar o artigo acima usando o Visual Studio Code em nosso canal do YouTube. Por favor, confira também o canal do YouTube.

YouTube Video