Эта статья моя последняя статья"Уголок ПВА"Расширение представляет Web Worker, связанный с Service Worker в PWA, я надеюсь, что это поможет вам, и, пожалуйста, дайте мне больше советов. Статьи на темы PWA будут выходить одна за другой, так что следите за обновлениями.
Введение
Web Worker (рабочий поток) — это концепция, предложенная в HTML5, которая делится на два типа: выделенный поток (Dedicated Web Worker) и общий поток (Shared Web Worker). Выделенный поток может использоваться только сценарием, который его создал (выделенный поток для основного потока), в то время как общий поток может использоваться в разных сценариях (общий поток для нескольких основных потоков).
Выделенные потоки можно рассматривать как веб-воркеры по умолчанию, и цель добавления модификаторов — отличить их от общих потоков. В этой статье мы будем строго различать эти два понятия, что может быть громоздко, но лично я считаю, что это необходимо. Если простоWeb Worker
Где появляются слова, относится к ситуации, когда присутствуют оба.
использовать
Важность Web Worker заключается в том, что некоторые трудоемкие операции обработки данных могут быть отделены от основного потока, чтобы основной поток мог больше сосредоточиться на рендеринге страницы и взаимодействии.
- ленивая загрузка
- Анализ текста
- Обработка данных потокового мультимедиа
- холст графика рисунок
- Обработка изображения
- ...
Нужно обратить внимание на точку
- Гомологическая рестрикция
- Не удается получить доступ к узлу DOM
- Работает в другом контексте, не может использовать объект Window
- Работа Web Worker не влияет на основной поток, но все же ограничена узким местом одиночного потока основного потока при взаимодействии с основным потоком. Другими словами, если рабочий поток часто взаимодействует с основным потоком, основной поток все равно может заблокировать страницу из-за необходимости обработки взаимодействия.
- Общие потоки могут вызываться несколькими контекстами просмотра, но все эти контексты просмотра должны иметь одно и то же происхождение (один и тот же протокол, хост и номер порта).
поддержка браузера
Согласно статистике CanI Use the site, в настоящее время около 93,05 процента браузеров поддерживают выделенный поток.
А для общих тредов его поддерживают только около 41,66% браузеров.
Поскольку конструкторы выделенных и общих потоков содержатся в объекте окна, мы можем судить о поддержке браузера, прежде чем использовать оба.
if (window.Worker) {
// ...
}
if (window.SharedWorker) {
// ...
}
создание темы
Специальная ветка отWorker()
Создание метода может принимать два параметра, первый параметр — это расположение требуемого скрипта, а второй параметр — необязательный объект конфигурации, который можно указатьtype
,credentials
,name
три свойства.
var worker = new Worker('worker.js')
// var worker = new Worker('worker.js', { name: 'dedicatedWorker'})
Использование общего потокаShared Worker()
Создание метода также поддерживает два параметра, использование такое же, какWorker()
Последовательный.
var sharedWorker = new SharedWorker('shared-worker.js')
Стоит отметить, что, поскольку Web Worker имеет такое же ограничение происхождения, к нему также необходимо получить доступ, запустив локальный сервер при локальной отладке, используяfile://
Если протокол открыт напрямую, будет выдано исключение.
Передача данных
И рабочий поток, и основной поток проходятpostMessage()
способ отправить сообщение черезonmessage
События получают сообщения. В этом процессе данные не передаются, а копируются. Стоит отметить, чтоError
а такжеFunction
Объекты не могут быть скопированы алгоритмом структурированного клонирования, и попытка сделать это приведет к броскуDATA_CLONE_ERR
исключение. Кроме того,postMessage()
За один раз можно отправить только один объект. Если вам нужно отправить несколько параметров, вы можете обернуть параметры в массив или объект и передать их.
оpostMessage()
а алгоритм структурированного клонирования (Thestructured clone algorithm) будет описан в конце этой статьи.
Ниже приведен пример передачи данных выделенного потока.
// 主线程
var worker = new Worker('worker.js')
worker.postMessage([10, 24])
worker.onmessage = function(e) {
console.log(e.data)
}
// Worker 线程
onmessage = function (e) {
if (e.data.length > 1) {
postMessage(e.data[1] - e.data[0])
}
}
В рабочем потокеself
а такжеthis
Оба представляют глобальные объекты для дочерних потоков. для мониторингаmessage
События, следующие четыре написания эквивалентны.
// 写法 1
self.addEventListener('message', function (e) {
// ...
})
// 写法 2
this.addEventListener('message', function (e) {
// ...
})
// 写法 3
addEventListener('message', function (e) {
// ...
})
// 写法 4
onmessage = function (e) {
// ...
}
основной нить черезMessagePort
Доступ к выделенным и общим темам. Порт выделенного потока автоматически устанавливается при создании потока и не отображается. В отличие от выделенных потоков, общие потоки должны иметь открытые порты перед передачей сообщений. на MDNMessagePort
оstart()
Описание метода такое:
Starts the sending of messages queued on the port (only needed when using EventTarget.addEventListener; it is implied when using MessagePort.onmessage.)
Это предложение было проверено и может быть понято какstart()
метод сaddEventListener
используются вместе. если мы выберемonmessage
Для мониторинга событий он будет неявно вызыватьсяstart()
метод.
// 主线程
var sharedWorker = new SharedWorker('shared-worker.js')
sharedWorker.port.onmessage = function(e) {
// 业务逻辑
}
var sharedWorker = new SharedWorker('shared-worker.js')
sharedWorker.port.addEventListener('message', function(e) {
// 业务逻辑
}, false)
sharedWorker.port.start() // 需要显式打开
При доставке сообщения,postMessage()
Методы иonmessage
События должны вызываться через объект порта. Кроме того, в потоке Worker необходимо использоватьonconnect
Событие прослушивает изменения порта и отвечает обработчиком сообщений порта.
// 主线程
sharedWorker.port.postMessage([10, 24])
sharedWorker.port.onmessage = function (e) {
console.log(e.data)
}
// Worker 线程
onconnect = function (e) {
let port = e.ports[0]
port.onmessage = function (e) {
if (e.data.length > 1) {
port.postMessage(e.data[1] - e.data[0])
}
}
}
близкий работник
можно использовать в основном потокеterminate()
метод или использование в рабочем потокеclose()
способ закрыть воркер. Эти два метода эквивалентны, но более рекомендуемым является использованиеclose()
, чтобы предотвратить случайное завершение работы рабочих потоков. Как только рабочий поток закрывает рабочий поток, рабочий больше не будет отвечать.
// 主线程
worker.terminate()
// Dedicated Worker 线程中
self.close()
// Shared Worker 线程中
self.port.close()
обработка ошибок
Может быть установлен в основном потоке или в рабочем потокеonerror
а такжеonmessageerror
Функция обратного вызова для обработки ошибки. в,onerror
В рабочемerror
Выполняется, когда событие срабатывает и всплывает,onmessageerror
Запускается, когда сообщение, полученное Worker, не может быть десериализовано (я пробовал и не могу запустить егоonmessageerror
событие, если используется в рабочем потокеpostMessage
Методы, передающие объект Error или Function, будут иметь приоритет, поскольку они не могут быть сериализованы.onerror
захват метода вообще без входа в процесс десериализации).
// 主线程
worker.onerror = function () {
// ...
}
// 主线程使用专用线程
worker.onmessageerror = function () {
// ...
}
// 主线程使用共享线程
worker.port.onmessageerror = function () {
// ...
}
// worker 线程
onerror = function () {
}
Загружать внешние скрипты
Веб-воркер предоставляетimportScripts()
чтобы иметь возможность загружать внешние файлы скриптов в Worker.
importScripts('script1.js')
importScripts('script2.js')
// 以上写法等价于
importScripts('script1.js', 'script2.js')
дочерний поток
Рабочие могут порождать детей-работников, но есть две вещи, на которые следует обратить внимание.
- Дочерние рабочие процессы должны иметь то же происхождение, что и родительская страница.
- URI в дочерних рабочих процессах разрешаются относительно того, где находится родительский рабочий процесс.
Встроенный рабочий
Нет ярлыка может сделать свой вид кода, как работник<script>
Элементы встроены в веб-страницы, но мы можемBlob()
Разберите рабочий код на странице.
<script id="worker" type="javascript/worker">
// 这段代码不会被 JS 引擎直接解析,因为类型是 'javascript/worker'
// 在这里写 Worker 线程的逻辑
</script>
<script>
var workerScript = document.querySelector('#worker').textContent
var blob = new Blob([workerScript], {type: "text/javascript"})
var worker = new Worker(window.URL.createObjectURL(blob))
</script>
О сообщенииСообщение
В Web Worker алгоритм структурированного клонирования используется для обмена данными между рабочим потоком и основным потоком. Алгоритм структурированного клонирования — это алгоритм, который создает клоны путем рекурсивного ввода объектов, избегая бесконечных циклов обхода за счет сохранения карты ранее посещенных ссылок. Этот процесс можно понимать как использование на стороне отправителя чего-то вродеJSON.stringfy()
Метод сериализует параметры на стороне получателя, используя что-то вродеJSON.parse()
способ десериализации.
Однако после передачи данных необходимо пройти через сериализацию и де сериализацию, если большое количество данных, то сам процесс также может вызвать проблемы с производительностью. Поэтому работника предложилTransferable Objects
Концепция, когда объем данных велик, мы можем выбрать передачу данных в основном потоке непосредственно в рабочий поток. Стоит отметить, что эта передача завершена, как только данные будут успешно переданы, основной поток не сможет получить доступ к данным. Этот процесс передачи еще продолжаетсяpostMessage
передавать.
postMessage(message, transferList)
Например, передайте объект ArrayBuffer
let aBuffer = new ArrayBuffer(1)
worker.postMessage({ data: aBuffer }, [aBuffer])
контекст
Работник работает вWorkerGlobalDataScope
в контексте. КаждыйWorkerGlobalDataScope
объекты разныеevent loop
. этоevent loop
Нет связанного контекста браузера (контекст просмотра), его очередь задач — это только события (events), обратные вызовы (callbacks) и сетевые действия (сетевая активность).
КаждыйWorkerGlobalDataScope
Имеетсяclosing
флаг, когда этот флаг установлен вtrue
, очередь задач будет отбрасывать задачи, которые попытаются присоединиться к очереди задач позже, и задачи, уже находящиеся в очереди, не будут затронуты (если не указано иное). При этом таймер перестанет работать, а все отложенные фоновые задачи будут удалены.
Функции и классы, которые можно использовать в Worker
Поскольку контекст работы Worker отличается от обычного контекста браузера, он не может получить доступ к окну и связанным с ним API-интерфейсам, а также не может напрямую манипулировать DOM. Работник обеспечиваетWorkerNavigator
а такжеWorkerLocation
интерфейс, они соответственно в окнеNavigator
а такжеLocation
подмножество . Кроме того, Worker также предоставляет различные интерфейсы, включая время, хранилище, сеть, рисование и т. д. Некоторые из них перечислены ниже.Документация MDN.
зависит от времени
- clearInterval()
- clearTimeout()
- setInterval()
- setTimeout
Связанный с работником
- importScripts()
- close()
- postMessage()
Связанные с хранением
- Cache
- IndexedDB
Связанные с сетью
- Fetch
- WebSocket
- XMLHttpRequest
Ссылки по теме
Ссылаться на
- Использование веб-воркеров — веб-API | MDN
- Worker | MDN
- MessagePort | MDN
- HTML Standard - Web workers
- Основная информация о веб-воркерах