JavaScript API: труженик Web Workers
В этой статье познакомимся с механизмом Web Workers, позволяющим организовать выполнение нескольких скриптов одновременно в фоновом режиме. Этот механизм является существенным изменением работы браузера.
Здравствуй, рабочий класс
Если новая функциональность для работы с файлами в браузерах, рассмотренная нами в предыдущем номере "КВ", не является такой уж новационной, то механизм параллельных вычислений - это то, чего в браузерах ещё не было. Если не считать, конечно, возможности организации параллельных вычислений с помощью дополнительного модуля GoogleGears, который существовал для некоторых браузеров и дальнейшее развитие которого, кстати, приостановлено.
А всё дело в том, что основная задача JavaScript первоначально была совсем незатейливой - обеспечить манипуляции с деревом DOM, или, проще говоря, обеспечить интерактивность веб-страницы на экране монитора. Различные несложные визуальные спецэффекты - вот и вся специфика применения JavaScript. Писать какие-то сложные вычисления на этом скриптовом языке никому и в голову не приходило.
Всё это время движок JavaScript в браузерах работал в однопоточном режиме. Так как основной задачей этого движка была только работа с DOM-деревом, дабы побаловать пользователя интерактивностью, такой однопоточности хватало за глаза. Добавление в JS-скрипт каких-то сложных числодробительных операций было делом неуместным, так как сразу же замедляло и тормозило отображение страницы в браузере. Сложные же вычисления производятся обычно на стороне сервера, а результаты возвращаются в браузер через интерфейс AJAX.
Однако незаметно наступила эпоха сложных веб-приложений. И эта эпоха потребовала выполнять часть вычислений не только на стороне сервера, но и на стороне браузера. А в дальнейшем предполагается экспансия офлайновых веб-приложений, в которых все производительные вычисления будут делаться только в браузере. И классическая однопоточность JavaScript совсем не соответствует требованиям времени.
Поэтому появление в браузерах механизма Web Workers можно считать ответом на вызовы текущей эпохи. С появлением механизма "веб-рабочий" можно числодробительные операции не отправлять на сервер, а выполнить их прямо в браузере. Причём это не должно сказываться на скорости основного скрипта, так как режим "рабочий" выполняется асинхронно.
Если же говорить образно, то раньше JavaScript в браузере можно было сравнить с офисным служащим, который просто перебирает в офисе бумажки и не выполняет какой-либо трудоёмкой работы. А теперь к этому "интеллигенту" в лице Web Workers добавлен настоящий работяга, который способен выполнять сложные, тяжёлые и продолжительные вычисления.
Техническая реализация
Познакомимся с веб-рабочим поближе. Механизм Web Workers позволяет запускать код JavaScript отдельным потоком. Чтобы задействовать этот механизм в браузере, сначала следует все числодробительные функции оформить отдельным файлом. После чего нужно просто создать экземпляр "рабочего", передав ему ссылку на этот отдельный файл.
new Worker('script.js');
В результате будет запущен отдельный поток, в котором будет выполнен загруженный код, а основной скрипт может спокойно продолжить свою работу с DOM-деревом, не ожидая завершения трудоёмких вычислений.
Конечно же, механизм Web Workers предполагает определённые нюансы и ограничения при взаимодействии с веб-страницей и вызвавшим его скриптом.
Во-первых, "веб-рабочий" не имеет никакого доступа к веб-странице и к её DOM-дереву. И это хорошо, потому как возможность доступа нескольких процессов одновременно к странице может обернуться настоящим кошмаром.
Во-вторых, взаимодействие основного скрипта и "веб-рабочего" происходит только через строковые сообщения посредством методов onmessage, postMessage. Сообщение может быть отослано "рабочему", так и "рабочий" может ответить родительской странице собственным сообщением.
Как и положено, проиллюстрируем сказанное примером очень высококачественного open source кода. Например, на веб-странице нам нужно просчитать локальный ядерный взрыв. Если считать этот взрыв в главном потоке, то эта веб-страница надолго зависнет, пока не выполнятся все расчёты. Поэтому лучше оформить ядерные вычисления в отдельный скрипт и запустить его через механизм Web Workers.
Листинг кода для веб-страницы
// Создаём рабочего var worker = new Worker("nuclear.js"); // Ожидание сообщений от worker worker.onmessage = function(e){ // Сообщение от worker: e.data; alert(e.data); }; // Запускаем worker worker.postMessage("go");
Листинг вспомогательного скрипта nuclear.js
onmessage = function(e){ if ( e.data == "go" ) { // Выполняем сложные вычисления var nuclear_explosion = "BABAH!!!"; // Отправляем полученный результат postMessage(nuclear_explosion); } };
Скрипт проверен в браузерах Firefox 3.7 и Opera 10.60, которые с недавних пор поддерживают этот режим выполнения JavaScript.
Резюме
Таким образом, как видим, в браузерах появилась функциональность, которая раньше обеспечивалась только через сервер. А теперь на стороне клиента есть и собственная БД в лице Web SQL, и собственная возможность произвести производительные вычисления Web Workers. В результате прикладная программа может работать очень гибко, когда в одном случае можно использовать внутренние вычислительные ресурсы, в другом случае могут использоваться облачные мощности.
Реализация механизма Web Workers, скорее всего, потребует возможностей операционных систем. Читатели на форуме после статьи о тестировании браузера Opera просили делать тесты браузеров на нескольких операционных системах. И здесь нужно заметить, что обычные JS-скрипты не используют системные возможности, и чистый JavaScript показывает в тестах практически одинаковые результаты - что на Windows, что на Linux. А вот режим Web Workers может продемонстрировать различия в скорости для разных ОС.
Михаил АСТАПЧИК
Горячие темы