Веб-работник — это сценарий JS, который выполняется в фоновом режиме отдельно от других сценариев, что позволяет нам внедрять многопоточность в наши веб-приложения. Хотя веб-работники не являются частью спецификации HTML5, их можно использовать с приложениями HTML5. В этом кратком совете мы рассмотрим, как их использовать.
Введение в веб-работников
На земле HTML5 у нас есть несколько очень интересных API. Некоторые из них — например, веб-работники — полезны для повышения производительности, что очень важно как для приложений, так и для игр. Но как веб-работники … ну, работают?
Каждый экземпляр веб-работника создает другой поток, в котором работает ваш JavaScript. Вы создаете один экземпляр так:
1
|
var worker = new Worker(‘filename.js’);
|
Здесь «filename.js» — это имя файла, содержащего ваш скрипт. Поскольку работники являются отдельными средами, вы не можете использовать код, встроенный непосредственно в HTML; Вы должны использовать отдельный файл.
Связь: отправка и получение данных
У рабочих нет доступа к DOM страницы или глобальному объекту, так как они общаются с сайтом? Это просто. Когда вы хотите отправить некоторые данные со своей страницы в Worker, вы вызываете postMessage()
.
Для этого требуется один параметр: данные для отправки, которые могут быть либо строкой, либо объектом, доступным для анализа в формате JSON (это означает, что вы не можете передавать функции или циклические ссылки, или вы получите DOM_EXCEPTION
). В некоторых браузерах существует проблема с объектами, поэтому всегда лучше вручную анализировать объект с помощью JSON.parse()
чтобы вам не приходилось беспокоиться о неполных реализациях.
То же самое происходит, если вы отправляете данные от Worker на страницу: просто вызовите postMessage()
для self
, который ссылается на глобальную область Worker. (Вы делаете это внутри сценария работника, конечно).
Затем для получения данных необходимо прикрепить onmessage
события onmessage
. Есть два способа сделать это, как с обычными событиями для элементов DOM; вы можете либо напрямую назначить некоторую функцию свойству onmessage
, либо использовать addEventListener()
.
1
2
3
4
5
6
7
8
9
|
// First way:
worker.onmessage = function (e) {
console.log(e.data);
}
// Second way:
worker.addEventListener(‘message’, function (e) {
console.log(e.data);
});
|
Это ваш выбор, какой метод использовать. В любом случае, параметр функции будет объектом event
, и данные, отправленные с помощью postMessage()
будут переданы через свойство data
этого события.
Внешние скрипты и библиотеки
Хорошо, но что если нам нужно использовать какую-нибудь внешнюю библиотеку? У нас нет доступа к DOM или глобальной области видимости, поэтому мы не можем просто внедрить скрипт.
Конечно, нам не нужно — для этого есть функция. Он называется importScripts()
и принимает один или несколько аргументов: имена сценариев для загрузки внутри области Worker. Вы должны знать, что скрипты, переданные в эту функцию, загружаются в случайном порядке, но они будут выполняться так, как указано, и выполнение скриптов будет приостановлено до тех пор, пока они не будут загружены.
1
2
|
importScripts(‘one-lib.js’);
importScripts(‘first-lib.js’, ‘second-lib.js’, ‘third-lib.js’);
|
Вы можете использовать importScripts
любом месте вашего кода, что упрощает создание запросов JSONP внутри Workers, как мы сделаем в следующем примере.
Пример: рабочие в действии
Правильно, теперь вы, вероятно, хотите увидеть Работника в действии. Вместо того, чтобы показывать что-то довольно бесполезное, например, получать простые числа или числа Фибоначчи, я решил сделать то, что вы, возможно, будете использовать после нескольких изменений.
Пример сценария (я включил только код Worker, остальное легко сделать) получит последние 100 твитов от @envatoactive (нам нужно установить счетчик 121 вместо 100, так как Tweeter API отправляет меньше твитов, чем просил — не спрашивайте меня почему, я не знаю).
Вот код, который будет находиться внутри самого файла сценария Web Worker:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
// Helper function for processing the data
var process = function (data) {
// Iterate through the data;
for (var i = 0, v; v = data[i]; i++) {
// And pass Tweet’s text to the page
self.postMessage({ text: v.text });
}
// After work is done, let the page know
self.postMessage(«finished»);
}
// Attach event listener to handle messages
self.addEventListener(‘message’, function (event) {
// Check if command sent was ‘start’
// Not necessary here, but may be useful later
if (event.data == «start») {
// Reply to the page that we started the work
self.postMessage(«started»);
// Core of the script, get the Tweets
// The callback parameter specifies the function to execute after the request is done
// (We call the process() function, defined above.)
// Count needs to be 121 because Tweeter API is sending lower amount of data than requested
importScripts(«http://twitter.com/statuses/user_timeline/envatoactive.json?callback=process&count=121»);
}
});
|
Должно быть легко понять, как это все работает из комментариев. Это позволяет вашему приложению загружать все твиты в фоновом режиме, используя отдельный поток.
Теперь попробуйте вставить следующий эквивалентный код, который не использует веб-работников, вместо заголовка пустой страницы и обратите внимание на задержку. (Это все еще мало, но представьте, если вы получаете не 100, а 100 000 твитов):
01
02
03
04
05
06
07
08
09
10
|
<script type=»text/javascript»>
var process = function (data) {
// Iterate through the data;
for (var i = 0, v; v = data[i]; i++) {
// And log Tweet’s text to the console
console.log(v.text);
}
}
</script>
<script src=»http://twitter.com/statuses/user_timeline/envatoactive.json?callback=process&count=121″></script>
|
Вывод
Как вы можете видеть, веб-работники предлагают вам простой способ убрать лаги из вашего графического интерфейса и перенести сложные вычисления или сетевое взаимодействие в отдельные потоки.
Я надеюсь, что вы узнали что-то новое из этой статьи — может быть, вы будете использовать Workers в вашем следующем проекте? Если у вас есть какие-либо вопросы или проблемы, пожалуйста, прокомментируйте ниже.