Web Workers позволяют выносить ресурсоемкие вычисления в отдельные потоки, предотвращая блокировку основного потока браузера. В Angular есть несколько способов их интеграции.
Самый простой способ - генерация через CLI:
ng generate web-worker app
Эта команда:
src/app/app.worker.ts
tsconfig.json
для поддержки workers/// <reference lib="webworker" />
addEventListener('message', ({ data }) => {
const result = heavyCalculation(data);
postMessage(result);
});
function heavyCalculation(data: any): any {
// Ресурсоемкие вычисления
return data.map(/* ... */);
}
const worker = new Worker(new URL('./app.worker', import.meta.url), {
type: 'module' // Важно для Angular
});
worker.postMessage(largeDataSet);
worker.onmessage = ({ data }) => {
console.log('Получены данные от worker:', data);
};
import { Observable, Observer } from 'rxjs';
function runInWorker<T>(worker: Worker, data: any): Observable<T> {
return new Observable((observer: Observer<T>) => {
worker.postMessage(data);
worker.onmessage = ({ data }) => {
observer.next(data);
observer.complete();
};
worker.onerror = (error) => {
observer.error(error);
};
});
}
ngOnDestroy() {
if (this.worker) {
this.worker.terminate();
}
}
Лучшая практика - вынести логику работы с worker в сервис:
@Injectable({ providedIn: 'root' })
export class WorkerService {
private worker: Worker;
constructor() {
this.worker = new Worker(new URL('./app.worker', import.meta.url), {
type: 'module'
});
}
processData(data: any): Observable<any> {
return new Observable(observer => {
this.worker.onmessage = ({ data }) => {
observer.next(data);
observer.complete();
};
this.worker.postMessage(data);
});
}
}
Нет доступа к DOM:
document
, window
Передача данных:
Transferable Objects
// Пример с Transferable
const arrayBuffer = new ArrayBuffer(1024);
worker.postMessage(arrayBuffer, [arrayBuffer]);
import * as Comlink from 'comlink';
// В worker
const api = { heavyTask: () => { /* ... */ } };
Comlink.expose(api);
// В основном потоке
const worker = new Worker('./worker', { type: 'module' });
const api = Comlink.wrap(worker);
await api.heavyTask();
import Worker from 'worker-loader!./app.worker';
const worker = new Worker();
ng generate web-worker
Идеальные кейсы для Web Workers:
Для большинства Angular-приложений достаточно встроенной поддержки workers через CLI. Для сложных сценариев рассмотрите Comlink или worker-loader.