Веб-воркер в TypeScript

Веб-воркер в TypeScript

В этой статье объясняется использование веб-воркеров в TypeScript.

Вы узнаете о концепции Web Workers и о различных советах по их использованию с примерами.

YouTube Video

Воркер в TypeScript

В TypeScript Worker представляет собой механизм выполнения обработки в фоновом режиме отдельно от основного потока, используя API веб-воркеров JavaScript. Это позволяет выполнять сложные вычисления и асинхронные задачи без влияния на работу пользовательского интерфейса.

Worker работает параллельно с основным потоком (потоком пользовательского интерфейса) и может обмениваться данными между потоками через сообщения. Даже в TypeScript можно использовать Worker, сохраняя безопасную работу с типами.

Основное использование воркера

  1. Создание воркера

    Создайте экземпляр Worker и выполните указанный скрипт. Как правило, скрипт определяется в отдельном файле.

  2. Обмен сообщениями

    Отправляйте и принимайте сообщения между основным потоком и потоком Worker, используя postMessage и onmessage.

Пример: базовая реализация воркера

  1. worker.ts: скрипт для воркера
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: скрипт для использования воркера в основном потоке
 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
  • В этом примере worker.ts работает в отдельном потоке, вычисляет сумму num1 и num2, а затем возвращает результат в основной поток. Основной поток принимает результат и выводит его в консоль.
  • Когда вы указываете type: 'module', скрипт Worker интерпретируется как ES-модуль, что позволяет использовать import и export. Это позволяет работать с модульной структурой без использования традиционной функции importScripts().

Моменты, которые нужно учитывать при использовании воркеров в TypeScript

Добавление определений типов

В TypeScript определяйте типы данных, чтобы гарантировать безопасное взаимодействие при отправке и приеме сообщений.

 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);
  • Указывая параметр типа для MessageEvent, можно четко определить тип данных, которые нужно получать. Это обеспечивает безопасный обмен данными по типу.

Настройка Webpack или Vite

При использовании Worker в TypeScript могут потребоваться сборщики, такие как Webpack или Vite. Используя эти инструменты, вы можете корректно собрать скрипт Worker и сделать его доступным для главного потока.

Например, при использовании Vite, используйте import.meta.url для корректного импорта Worker.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
  • Это гарантирует правильную загрузку собранного скрипта Worker, позволяя использовать его для обработки задач.

Особенности обмена сообщениями и параллельной работы

  1. Копирование данных

    При отправке и получении сообщений между главным потоком и потоком Worker данные копируются. При работе со сложными данными, такими как объекты, необходимо учитывать эффективность. Частая передача больших объемов данных может снизить производительность.

  2. Передаваемые объекты

    Некоторые объекты, такие как ArrayBuffer, называются передаваемыми (Transferable) объектами. Передаваемые (Transferable) объекты можно передавать Worker, а не копировать при обмене сообщениями. Это позволяет избежать накладных расходов, связанных с копированием данных.

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)
  • Передавая [buffer] в качестве второго аргумента в worker.postMessage(), вы передаете buffer Worker, а не копируете его.

  • После этого buffer в главном потоке становится пустым (его byteLength равен 0) и может использоваться только Worker.

Завершение работы Worker

Worker следует завершать после использования, чтобы минимизировать потребление памяти. Вы можете завершить Worker, используя метод terminate.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2// ...
3
4worker.terminate(); // Terminate the Worker
  • Этот код завершает работу Worker с помощью метода terminate.

Обработка исключений в Worker

Если в Worker происходит ошибка, вы можете обработать её с помощью события 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};
  • Этот код перехватывает и обрабатывает ошибки, возникающие внутри Worker, с помощью события onerror.

Резюме

Используя Worker в TypeScript, вы можете выполнять тяжёлые задачи в фоновом режиме, сохраняя плавность работы главного потока. Используя определения типов, обмен сообщениями также может быть выполнен безопасным с точки зрения типов образом. Обращая внимание на обмен данными и управление потоками, вы можете добиться улучшения производительности и эффективной параллельности.

Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.

YouTube Video