Веб-воркер в TypeScript
В этой статье объясняется использование веб-воркеров в TypeScript.
Вы узнаете о концепции Web Workers
и о различных советах по их использованию с примерами.
YouTube Video
Воркер в TypeScript
В TypeScript Worker
представляет собой механизм выполнения обработки в фоновом режиме отдельно от основного потока, используя API веб-воркеров JavaScript. Это позволяет выполнять сложные вычисления и асинхронные задачи без влияния на работу пользовательского интерфейса.
Worker
работает параллельно с основным потоком (потоком пользовательского интерфейса) и может обмениваться данными между потоками через сообщения. Даже в TypeScript можно использовать Worker
, сохраняя безопасную работу с типами.
Основное использование воркера
-
Создание воркера
Создайте экземпляр
Worker
и выполните указанный скрипт. Как правило, скрипт определяется в отдельном файле. -
Обмен сообщениями
Отправляйте и принимайте сообщения между основным потоком и потоком
Worker
, используяpostMessage
иonmessage
.
Пример: базовая реализация воркера
- 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};
- 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
, позволяя использовать его для обработки задач.
Особенности обмена сообщениями и параллельной работы
-
Копирование данных
При отправке и получении сообщений между главным потоком и потоком
Worker
данные копируются. При работе со сложными данными, такими как объекты, необходимо учитывать эффективность. Частая передача больших объемов данных может снизить производительность. -
Передаваемые
объектыНекоторые объекты, такие как
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-канал.