Общие рабочие процессы

Общие рабочие процессы.

Тот тип рабочих процессов, с которым мы познакомились ранее, называется выделенным рабочим процессом (Dedicated Worker). Выделенный рабочий процесс отправляет ответы только главному коду, который его создал. Существуют также общие рабочие процессы, умеющие взаимодействовать с разными документами из одного источника. Работа с несколькими подключениями означает, что к одному и тому же рабочему

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

Соединение происходит через порты, которые можно сохранять в рабочем процессе для последующих обращений. Для использования общих рабочих процессов и портов в этой части API созданы новые свойства, события и методы:

— SharedWorker(scriptURL). Этот конструктор заменяет собой уже знакомый вам конструктор Worker(), предназначенный для выделенных рабочих процессов. Как всегда, атрибут scriptURL объявляет путь к JavaScript-файлу с кодом рабочего процесса. Можно также добавить необязательный второй атрибут, чтобы указать имя рабочего процесса; О port. При создании нового объекта SharedWorker для этого документа одновременно создается новый порт, который сохраняется в свойстве port. В дальнейшем посредством этого свойства происходят обращение к порту и обмен данными с рабочим процессом;

— connect. Это специальное событие, предназначенное для проверки наличия новых подключений изнутри рабочего процесса. Оно срабатывает каждый раз, когда из документа открывается новое соединение с рабочим процессом. Это событие удобно применять для отслеживания всех подключений, доступных для рабочего процесса (и обращения ко всем документам, использующим этот рабочий процесс);

— start(). Этот метод доступен для объектов MessagePort (один из объектов, возвращаемых при создании общего рабочего процесса). Он начинает отправку сообщений, приходящих на порт. Этот метод необходимо вызвать для того, чтобы открыть соединения после создания объекта SharedWorker.

Конструктор SharedWorker() возвращает объекты SharedWorker и Mes-sagePort, а также значение порта, через который будет осуществляться соединение с рабочим процессом. Обмен данными с общим рабочим процессом может происходить только через порт, значение которого содержится в свойстве port.

Для тестирования общих рабочих процессов нам потребуются минимум два разных документа в одном источнике, два файла с JavaScript-кодом (по одному для каждого документа) и файл с кодом рабочего процесса. Документ HTML для нашего примера включает в себя фрейм iframe, позволяющий загрузить второй документ в том же окне. И главный документ, и документ из iframe будут общаться с одним и тем же рабочим процессом (листинг 14.10).

<!DOCTYPE html>

<html lang="ru">

<head>

<title>Рабочие процессы</title>

<link rel="stylesheet" href="webworkers. css">

<script src="webworkers. js"></script>

</head>

<body>

<section id="formbox">

<form name="form">

<p>Имя:<br><input type="text" name="name" id="name"></p> <p><input type="button" name="button" id="button" value="Отправить"></p>

</form>

</section>

<section id="databox">

<iframe id="iframe" src="iframe. html" width="500" height="350"></iframe>

</section>

</body>

</html>

Документ, определяющий iframe, — это простой код HTML с разделом <section> для уже знакомого нам блока databox, включающий в себя ссылку на файл iframe. js, в котором находится код для соединения с рабочим процессом (листинг 14.11).

Листинг 14.11. Шаблон для фрейма iframe (iframe. html)

<!DOCTYPE html>

<html lang="ru">

<head>

<title>OKHO iframe</title>

<script src="iframe. js"></script>

</head>

<body>

<section id="databox"></section>

</body>

</html>

С каждым из документов HTML связан собственный JavaScript-код, открывающий соединение с рабочим процессом и обрабатывающий приходящие от него ответы. В обоих фрагментах необходимо создать объект SharedWorker и использовать для отправки и получения сообщений порт из свойства port. Давайте сначала рассмотрим код для главного документа.

Листинг 14.12. Подключение к рабочему процессу из главного документа (webworkers. js)

Function initiate(){

Var button=document. getElementById(‘button’); button. addEventListener(‘click’, send, false);

Worker=new SharedWorker(‘worker. js’);

Worker. port. addEventListener(‘message’, received, false); worker. port. start();

}

Function received(e){ alert(e. data);

}

Function send(){

Var name=document. getElementById(‘name’).value; worker. port. postMessage(name);

}

Window. addEventListener(‘load’, initiate, false);

В каждом документе, который должен обращаться к общему рабочему процессу, необходимо создать объект SharedWorker и установить соответствующее соединение. В коде из листинга 14.12 мы создаем объект рабочего процесса, ссылаясь на файл worker. js, а затем выполняем операции по обмену данными, используя соответствующий порт, сохраненный в свойстве port.

После того как добавлен прослушиватель события message, обеспечивающий возможность отлавливания ответов рабочего процесса, мы вызываем метод start(), чтобы начать отправку сообщений. Подключение к общему рабочему процессу не создается до тех пор, пока не будет выполнен этот метод (если только мы не используем вместо метода addEventListener() обработчики событий, такие как onmessage). Обратите внимание на то, что функция send() почти такая же, как в предыдущих примерах, только на этот раз обмен данными осуществляется с учетом значения свойства port.

Код фрейма также почти не меняется.

Листинг 14.13. Подключение из фрейма iframe (iframe. js)

Function initiate(){

Worker=new SharedWorker(‘worker. js’);

Worker. port. addEventListener(‘message’, received, false); worker. port. start();

}

Function received(e){

Var databox=document. getElementById(‘databox’); databox. innerHTML=e. data;

}

Window. addEventListener(‘load’, initiate, false);

В обоих примерах кода объект SharedWorker создается с использованием ссылки на один и тот же файл (worker. js), а подключение устанавливается посредством свойства port (хотя значения портов и различаются). Единственное существенное отличие кода главного документа от кода iframe заключается в том, каким образом обрабатывается ответ от рабочего процесса. В главном документе функция received() создает всплывающее сообщение (см. листинг 14.12), а в iframe ответ выводится в форме простого текста внутри блока databox (см. листинг 14.13).

Теперь настало время посмотреть, как же общий рабочий процесс справляется со всеми этими подключениями, отправляя правильные ответы в соответствующие документы. Как вы помните, у нас есть только один рабочий процесс для обоих документов — именно поэтому он называется общим. Таким образом, рабочему процессу необходимо как-то различать запросы и сохранять подключения для использования в дальнейшем. Мы будем записывать ссылки на порты всех документов в массив под названием myports.

Листинг 14.14. Код общего рабочего процесса (worker. js) myports=new Array();

AddEventListener(‘connect’, connect, false);

Function connect(e){

Myports. push(e. ports[0]);

E. ports[0].onmessage=send;

Function send(e){

For(f=0; f < myports. length; f++){

Myports[f].postMessage(‘Ваше имя: ‘+e. data);

}

}

Процедура аналогична той, которую мы описывали для выделенных рабочих процессов. На этот раз необходимо учитывать только то, какому документу отправляется ответ, так как к одному рабочему процессу одновременно могут подключаться несколько документов. Для этого мы используем массив ports события connect, в котором содержится значение последнего созданного порта (то есть в массиве есть только одно значение в позиции 0).

Каждый раз, когда код запрашивает подключение к рабочему процессу, срабатывает событие connect. В коде из листинга 14.14 это событие вызывает функцию connect(). В этой функции мы выполняем две операции. Во-первых, извлекаем значение порта из свойства ports (в позиции 0) и сохраняем в массиве myports (который инициализировали в начале рабочего процесса). Во-вторых, регистрируем обработчик события onmessage для этого конкретного порта и указываем, что при получении сообщения будет вызываться функция send().

Для тестирования этого примера вам понадобится создать и загрузить на свой сервер несколько файлов. Создайте HTML-файл с шаблоном из листинга 14.10, присвоив ему любое название на выбор. Этот шаблон будет загружать тот же файл webworkers. css, который мы используем на протяжении всей главы, файл webworkers. js с кодом из листинга 14.12 и файл iframe. html в качестве источника для создания фрейма (этот файл должен содержать код из листинга 14.11).

Кроме того, нужно создать файл с именем worker. js и поместить в него код рабочего процесса из листинга 14.14. После того как все файлы будут сохранены на сервере, откройте первый документ в своем браузере. Отправьте сообщение в рабочий процесс с помощью формы и посмотрите, как оба документа (главный документ и документ во фрейме) обработают ответ.

В результате, когда из главного кода в рабочий процесс отправляется сообщение — причем неважно, из какого документа, — происходит вызов функции send(). Внутри функции в цикле for мы извлекаем из массива myports все открытые порты для данного рабочего процесса и отправляем сообщения во все подключенные документы. Принцип работы ничем не отличается от описанного ранее для выделенных рабочих процессов, только на этот раз ответ отправляется в несколько документов, а не в один.

На момент написания этой главы общие рабочие процессы реализованы только в браузерах на базе механизма WebKit, таких как Google Chrome и Safari.

API Web Workers (Рабочие процессы) — краткий справочник

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

Рабочие процессы

Существует два типа рабочих процессов: выделенные и общие. Тем не менее следующие методы и события работают одинаково для обоих типов:

— postMessage(message). Этот метод отправляет сообщение рабочему процессу, главному коду или на соответствующий порт. В атрибуте message содержится строка или JSON-объект с нужным сообщением; О terminate(). Этот метод останавливает рабочий процесс из главного кода;

— close(). Этот метод останавливает рабочий процесс изнутри него самого;

— importScripts(file). Этот метод загружает внешний JavaScript-файл для добавления к рабочему процессу нового кода. Атрибут file содержит путь к нужному файлу;

— message. Это событие срабатывает, когда в код отправляется сообщение. Его можно использовать в рабочем процессе для прослушивания сообщений от главного кода и наоборот;

— error. Это событие срабатывает, когда в рабочем процессе происходит ошибка. Оно используется в главном коде для отслеживания ошибок рабочего процесса. Событие возвращает три свойства: message, filename и lineno. Свойство message представляет собой сообщение об ошибке, свойство filename содержит имя файла с кодом, вызвавшим ошибку, а свойство lineno возвращает номер строки, где произошла ошибка.

Выделенные рабочие процессы

Для создания выделенных рабочих процессов предназначен отдельный конструктор:

— Worker(scriptURL). Возвращает объект Worker. Атрибут scriptURL содержит путь к файлу с кодом рабочего процесса.

Общие рабочие процессы

Из-за особенностей самой природы общих рабочих процессов в данном API потребовалось создать несколько методов, событий и свойств, предназначенных только для такого типа рабочих процессов:

— SharedWorker(scriptURL). Этот конструктор возвращает объект SharedWorker. Атрибут scriptURL содержит путь к файлу с кодом общего рабочего процесса. Также можно добавить необязательный второй атрибут name, если требуется указать имя рабочего процесса;

— port. Это свойство возвращает значение порта, через который установлено соединение с рабочим процессом;

— connect. Это событие срабатывает в рабочем процессе, когда документ запрашивает новое подключение;

— start(). Этот метод запускает отправку сообщений. Он используется для открытия подключения к рабочему процессу.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *