Перейти к содержанию

Web Workers

Web Worker представляет собой механизм запуска выполнения скрипта отдельным процессом в фоновом режиме. Причем Web Worker-ы могут создавать другие и так далее. Общение между главным процессом и Web Worker-ами осуществляется с помощью сообщений.

Создание Web Worker через Angular CLI

Сперва для примера создадим новый проект.

ng new web-worker-app

Теперь для добавления Web Worker в приложение, воспользуйтесь следующей командой Angular CLI.

ng g web-worker app

Здесь в команде app является компонентом, для которого необходимо создать Angular Web Worker.

Если это первый Web Worker в приложении, то выполнение команды обновит конфигурацию проекта для возможности работы с Angular Web Worker, при этом будет создан файл tsconfig.worker.json со следующим содержимым

tsconfig.worker.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/worker",
    "lib": ["es2018", "webworker"],
    "types": []
  },
  "include": ["src/**/*.worker.ts"]
}

Также будет создан файл app.worker.ts (в зависимости от компонента название может быть другим), который по умолчанию будет содержать такой код.

app.worker.ts

/// <reference lib="webworker" />

addEventListener('message', ({ data }) => {
  const response = `worker response to ${data}`
  postMessage(response)
})

А в коде самого компонента app.components.ts появится следующее.

app.component.ts

if (typeof Worker !== 'undefined') {
  // Create a new
  const worker = new Worker('./app.worker', {
    type: 'module',
  })
  worker.onmessage = ({ data }) => {
    console.log(`page got message: ${data}`)
  }
  worker.postMessage('hello')
} else {
  // Web Workers are not supported in this environment.
  // You should add a fallback so that your program still executes correctly.
}

Теперь можно заменить код по умолчанию своей реализацией.

Angular Universal не поддерживает работу Web Worker-ов, поскольку они являются частью браузерного API.

Web Worker API

Отправка сообщения из главного процесса Web Worker-у и наоборот осуществляется с использованием метода postMessage(), параметрами принимающий данные, которые необходимо доставить.

untitled.ts

worker.postMessage('hello')

Получение отправленных данных инициирует событие message, callback-функции которого аргументом передается экземпляр объекта MessageEvent, в свойстве data которого находятся переданные данные.

untitled.ts

worker.onmessage = ({ data }) => {
  console.log(`page got message: ${data}`)
}

Обработка ошибок осуществляется с помощью события error.

untitled.ts

worker.onerror = (err) => {
  console.log(
    `${err.filename}:${err.lineno} ${err.message}`
  )
}

Объект ошибки имеет следующие свойства:

  • filename - имя файла, в котором произошла ошибка;
  • lineno - номер строки, на которой возникла ошибка;
  • message - текст ошибки.

Для завершения работы Angular Web Worker-а вызовите у его экземпляра метод terminate().

untitled.ts

worker.terminate()

Выделенные и разделяемые Web Worker-ы

Имеется два типа Web Worker-ов: выделенные и разделяемые.

Выделенные Web Worker-ы создаются через new Worker() и доступны для использования только тому скрипту, который его создал. Параметром конструктору передается путь к скрипту, который должен быть запущен в отдельном процессе.

По умолчанию Angular Web Worker относится к выделенным.

app.component.ts

@Component({
  selector: 'app-root',
  template: `
    <button (click)="getData()">Get data</button>
  `,
})
export class AppComponent {
  worker: Worker

  constructor() {
    if (typeof Worker !== 'undefined') {
      this.worker = new Worker('./app.worker', {
        type: 'module',
      })

      this.worker.addEventListener(
        'message',
        (message: MessageEvent) =>
          console.log(
            'Got data from worker: ',
            message.data
          )
      )
    } else alert('Web Worker is not supported.')
  }

  getData(): void {
    this.worker.postMessage('Give me data')
  }
}

app.worker.ts

/// <reference lib="webworker" />

addEventListener('message', (message: MessageEvent) => {
  console.log('Got message from main: ', message.data)
  postMessage('Data for main')
})

В отличие от выделенных, разделяемые Web Worker-ы доступны множеству скриптов, которые причем могут находиться в разных окнах.

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

Ссылки

Комментарии