Веб-воркер в 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(), вы передаетеbufferWorker, а не копируете его. -
После этого
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-канал.