Angular & Web Workers

Danilo Lima
5 min readMar 29, 2024

--

Durante muito tempo, uma das principais preocupações quando o assunto envolvia performance de aplicações web era com a quantidade e complexidade do código JavaScript sendo executado no navegador, o JavaScript, sendo uma linguagem single-threaded, exigia mais atenção quanto a esse aspecto.

Porém, com a especificação do HTML 5 isso mudou um pouco, e nesse contexto vamos explorar a API de Web Workers no cenário do Angular, o intuito é te familiarizar sobre como interagir com a API de Web Workers tanto ao usar puramente JavaScript e também com o framework, vamos nessa!

Angular e Web Workers

O que são Web Workers?

No contexto web, ele é um termo popular que se refere a API de Web Workers, que começou a ser especificada em 2004 com o HTML 5, e foi lançada oficialmente em 2014, o intuito dessa especificação foi permitir que código JavaScript pudesse ser executado em paralelo a thread principal.

Isto abriu uma série de possibilidades, pois agora é possível executar tarefas complexas do lado do cliente, em um ambiente que possui seu próprio escopo, sem afetar a experiência do usuário.

Processamento de dados, Operações I/O assíncronas, Tarefas em segundo plano, Cache, Simulações e Modelagens são apenas algumas das tarefas que podemos executar com um worker, que, se fossem executadas na thread principal do JavaScript, certamente impactariam negativamente a experiência do usuário da sua aplicação.

Implementando Web Workers

Chega de falar!

Vamos colocar a mão na massa, a implementação é relativamente simples e nesse exemplo vamos precisar apenas de uma página carregando alguns scripts.

Nossa página

Vamos criar uma página HTML bem simples…

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Worker - Exemplo</title>
</head>
<body>
<h1 id="result"></h1>
</body>
</html>

Adicionando nosso script

Vamos incluir o script que irá se comunicar com nosso worker, perceba que a comunicação entre eles é baseada em eventos, é extremamente simples:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Worker - Exemplo</title>
<script>
// Verifica se os Web Workers são suportados pelo seu browser
if (window.Worker) {
// Criamos um novo Web Worker
const myWorker = new Worker('worker.js');

// Enviamos uma mensagem para o Web Worker
myWorker.postMessage(10);

// Aqui escutamos por mensagens vindas do Web Worker
myWorker.onmessage = function({ data }) {
const element = document.querySelector("#result");
element.innerText = data;
};

// Apesar de não ser o foco desse post,
// também podemos escutar por erros no Web Worker
myWorker.onerror = function(error) {
console.error('error:', error);
};
} else {
console.log('Seu navegador não tem suporte para Web Workers.');
}
</script>
</head>
<body>
<h1 id="result"></h1>
</body>
</html>

Adicionando nosso Web Worker

Não tem muita novidade, o worker é só um código JavaScript que vamos criar em um arquivo worker.jsno mesmo diretório…

function fib(n) {
if(n <= 1){
return n;
}else {
return fib(n-1) + fib(n - 2);
}
}

// Enviamos a mensagem de volta para o script que chamou o worker
addEventListener('message', ({ data }) => {
const response = fib(data);
postMessage(response);
});

Usei uma extensão do VSCODE para servir o arquivo HTML e voilà! Eis o nosso resultado!

Resultado web worker rodando com live server

Apareceu bem rápido, mas você pode passar valores acima de 10 para o worker e perceber que não impacta na performance da página que você está visualizando esperando o resultado, apesar de levar algum tempo para o worker processar.

Mas como funciona no Angular?

No angular é mamão com açúcar.

Primeiro, garanta que tenha o Angular CLI instalado e crie um projeto novo:

ng new app-worker

Com o projeto criado, navegue com o terminal até o diretório do projeto e execute o comando abaixo:

ng g web-worker app

A CLI do Angular vai alterar algumas coisas no seu projeto para deixá-lo no jeitinho pra você usar os Web Workers no Framework, ele basicamente:

  1. Altera o arquivo a configuração de build no arquivo angular.json do seu projeto
  2. Cria um arquivo app.worker.ts com um código Typescript de exemplo, que vamos substituir a seguir;
  3. Cria um arquivo tsconfig.worker.json com algumas configurações;
  4. E também inclui um código Typescript chamando o worker a partir do seu arquivo app.component.ts;

E só precisaremos de dois passos :

  1. Trazendo o código do nosso worker para arquivo app.worker.ts
/// <reference lib="webworker" />
function fib(n: number) {
if(n <= 1){
return n;
}else {
return fib(n-1) + fib(n - 2);
}
}
addEventListener('message', ({ data }) => {
const response = fib(data);
postMessage(response);
});

2. Ajustando a chamada ao nosso worker ao estilo Angular

import { Component, OnInit, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';

@Component({
selector: 'app-root',
standalone: true,
imports: [FormsModule],
template: '<h1>{{ result() }}</h1>',
})
export class AppComponent implements OnInit {
result = signal(0);
ngOnInit(): void {
if (window.Worker) {
const worker = new Worker(new URL('./app.worker', import.meta.url));
worker.onmessage = ({ data }) => {
this.result.set(data);
};
worker.postMessage(10);
}
}
}

Agora é só executar:

npm start

E esse é nosso resultado:

Resultado web worker com Angular

Conclusão

E é isso meu querido(a), as possiblidades com Web Workers são muitas no que diz respeito principalmente a performance das suas aplicações web, você não tem desculpa para poluir a thread principal do JavaScript com processamento pesado agora que tem essa ferramenta, aliás, isso não era recomendação nem quando os Web Workers ainda não existiam!

Claro que, seria ótimo poder processar o máximo que pudermos nos web workers, mas como nem tudo são flores, você pode se deparar com algumas limitações, por isso sugiro que leia mais sobre essa API para entender onde ela se encaixa na sua aplicação da melhor forma.

Muito obrigado por ter chegado até aqui, já que está aqui, apoie meu trabalho clicando no botãozinho de palmas ali em baixo, quem sabe não chega esse post não chegue para alguém que precisa entender sobre workers.

Me me siga aqui na plataforma para ficar por dentro dos próximos posts, bem como no Linkedin, produzo conteúdo por lá também

Te vejo numa próxima, dev! 😉

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers

--

--

Danilo Lima
Danilo Lima

Written by Danilo Lima

Software developer working mainly with Frontend and Angular, Open Source Contributor and I usually give my 20 cents about technology and career.

No responses yet