Оглавление Предыдущая лекция Следующая лекция
Введение в HTML5
10. Лекция: Web Workers за работой: версия для печати и PDA
Введение в технологию многопоточного выполнения кода Web Workers. Принципы работы и случаи использования. Какие стандартные объекты JavaScript доступны для Web Workers. Присущие ему ограничения. Поддержка в современных браузерах. Дополнительные ссылки по теме.

Дэниел Дэвис · 1 июля 2010 г.

Введение

Представьте следующее. Вы являетесь любимым руководителем малоизвестной страны ScravaJipt, безраздельно властвуя над всем, что обозреваете. У вас есть главный слуга, который ухаживает за вами, покупает одежду, нажимает кнопки на мобильном телефоне. Но иногда он со всем не справляется. Он бывает перегружен всеми этим повседневными заботами, так что приходится передавать часть работы специалистам (один для нажатия кнопок, еще один для покупки рубашек, другой для покупки брюк). К счастью для него имеется множество работников, на которых можно положиться. Аналогично, к счастью для разработчиков web существуют виртуальные цифровые специалисты, которые могут взять на себя некоторые задачи, когда процессор JavaScript становится перегруженным. Познакомьтесь с Web Workers, одной из множества технологий, которые, совместно с HTML5 формируют следующее поколение открытой Web.

Введение в технологию Web Workers

Встречали ли вы страницу, которая отображается частично, но не отвечает ни на какие щелчки? Или страницу, которая замораживается или приводит к аварийной остановке браузер?

Причина была, скорее всего, в JavaScript. Страницы Web становятся все в большей степени перегружены JavaScript, иногда в такой степени, что не могут двигаться. Вездесущность JavaScript является благом для разработчиков, но это означает, что язык может выполняться на широком множестве устройств, включая такие, которым не хватает мощности для сегодняшних приложений Web. Существует несколько способов оптимизации JavaScript, но он все равно не будет работать так же быстро, как машинный код.

Разработчики Web не собираются (и не должны) в связи с этим сокращать свое использование JavaScript. Вместо этого, стандарты Web и браузеры, которые их реализуют, продвигаются вперед, чтобы выдержать нагрузку. Технология Web Workers является этому примером, вместе с различными другими API JavaScript, которые разработаны для повышения возможностей браузера.

Как работают Web Workers

Большинство современных языков программирования являются мультипоточными, т.е. они могут выполнять несколько процессов одновременно. Превращение JavaScript в мультипоточный язык потребует значительных архитектурных изменений и фундаментального переосмысливания, поэтому Web Workers предлагают способ обойти эту проблему, позволяя расширить язык таким образом, что он может казаться в некоторых случаях мультипоточным. Другими словами может эффективно выполняться более одного процесса, но с некоторыми ограничениями. На самом деле достаточно много ограничений, поэтому они будут полезны только в определенных ситуациях.

Когда я могу их использовать?

Возвращаясь к нашей аналогии со "специалистами" можно сказать, что Web Workers могут делать только одну вещь, но они делают ее очень хорошо. Они прекрасно справляются с выполнением быстрых вычислений, но не могут сделать более сложную работу, такую как доступ к DOM. Если сравнить web-приложение с кухней, то основной поток JavaScript будет шеф-поваром, собирающимся приготовить омлет. Если он делает все самостоятельно, он должен взбить яйцо, подготовить сковородку, растопить масло и, наконец, приготовить омлет. Если он хочет повысить эффективность, он может получить помощь от кухонного работника. Работник может взбить яйцо, позволяя шеф-повару подготовить сковороду и масло, и затем приготовить омлет. Работнику не разрешается прикасаться к сковороде или готовить омлет – он просто выполняет задачу, в то время как шеф-повар продолжает с другой работой.

Если бы Web Workers мог готовить, вот как бы он помог приготовить омлет

Если бы Web Workers мог готовить, вот как бы он помог приготовить омлет

Использование Web Workers такое же. Если JavaScript содержит какие-то интенсивные вычисления с ресурсами, можно передать это Web Worker для обработки, в то время как основной процесс продолжает выполняться. Можно использовать более одного Web Worker, и Web Worker может делать более одной задачи. Давайте приготовим пример, чтобы увидеть это в действии.

Покажите мне просто код!

Сохраняйте спокойствие, мы прибываем на место! Работник (worker) сам является просто некоторым кодом JavaScript в своем собственном файле. Также как концепция Web Workers является выполнением кода в отдельном потоке, так и код самого работника должен находиться в отдельном файле, или нескольких файлах, если используется больше одного работника. В нашем примере давайте начнем с создания пустого текстового файла, который назовем worker.js.

В нашем основном потоке JavaScript мы используем работника, создавая новый объект Worker:

Основной поток JavaScript

var worker = new Worker('worker.js');

Как и с кухонным помощником, мы передаем работнику что-то, он делает что-то с этим в фоновом режиме, и затем что-то нам возвращает. Коммуникация с работником осуществляется с помощью метода postMessage:

Основной поток JavaScript

// Создаем новый объект работника 
var worker = new Worker('worker.js');

// Посылаем простое сообщение, чтобы запустить работника 
worker.postMessage();

Можно также передать работнику переменную:

Основной поток JavaScript

// Создаем новый объект работника
var worker = new Worker('worker.js');

// Посылаем сообщение, чтобы запустить работника 
// и передаем ему переменную 
var info = 'Web Workers';
worker.postMessage(info);

В работнике, т.е. внутри файла worker.js, мы используем событие onmessage для получения сообщения из основного потока и выполнения какой-то работы. Если предается переменная, то можно получить к ней доступ с помощью event.data следующим образом:

worker.js
// Получаем сообщение из основного потока 
onmessage = function(event) {
// Выполняем что-то 
var info = event.data;
};

Отправка сообщений из работника назад в основной поток использует те же методы:

worker.js
// Получить сообщение из основного потока 
onmessage = function(event) {
// Сделать что-то
var info = event.data;
var result = info + ' rise up!';
postMessage(result);
};
Main JavaScript thread
// Создать новый объект worker 
var worker = new Worker('worker.js');

// Послать сообщение, чтобы запустить работника и
// передать ему переменную 
var info = 'Web Workers';
worker.postMessage(info);

// Получить сообщение от работника
worker.onmessage = function (event) {
// Сделать что-то
alert(event.data);
};

При желании можно загрузить следующий демонстрационный пример использования Web Workers (http://dev.opera.com/articles/view/web-workers-rise-up/WebWorkers_demo.zip).

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

О чем надо помнить

Это, очевидно, очень простой пример, но когда вы задаете работникам более сложные задачи, такие как управление большими массивами, или вычисление точек в трехмерном пространстве для отображения в основном потоке, то это становится очень мощным средством. Основное, что надо помнить, однако, состоит в том, что работники не могут получить доступ к DOM. В примере выше, например, мы не можем вызвать внутри работника alert() или даже document.getElementById() - он может только получать и возвращать переменные, хотя это могут быть строки, массивы, объекты JSON, и т.д.

Вот сводка того, что доступно и недоступно для Web Workers.

Могут использовать:

  • объект navigator
  • объект location (только чтение)
  • метод importScripts() (для доступа к файлам сценариев в том же домене)
  • объекты JavaScript, такие как Object, Array, Date, Math, String
  • XMLHttpRequest
  • методы setTimeout() и setInterval()

Не могут использовать:

  • DOM
  • Порождающую работника страницу (только через postMessage())

Поддержка браузеров

На момент написания не все браузеры поддерживали Web Workers, поэтому их надо использовать с осторожностью. Вместо того чтобы пытаться отследить, какие версии браузеров поддерживают и не поддерживают, проще включить проверку внутри сценария. Чтобы определить, поддерживает ли браузер пользователя Web Workers, можно проверить существование свойства Worker объекта window:

// Проверка, что имеется поддержка Web Workers 
if (!!window.Worker) {
// Ура, можно передать утомительную работу!
}

Web Workers особенно подходят в тех ситуациях, где нежелательно заставлять пользователя ждать, пока выполняется какой-то код. Основной поток вычислений может сконцентрироваться на работе с UI, отображая его как можно быстрее, в то время как Web Workers могут в фоновом режиме обрабатывать данные, используя AJAX для коммуникации с сервером. Все счастливы, и все прекрасно в стране ScravaJipt.

Дополнительные ссылке по теме Web Workers

© INTUIT.ru