Если вы новичок в HTML 5 Web Workers, то я рекомендую вам прочитать мой предыдущий пост, в котором подробно описаны различные типы веб-работников, которые доступны, как создавать рабочие объекты и как общаться между работником и его создателем.
Если у вас есть веб-сайт (или веб-приложение) с несколькими окнами, каждое из которых нуждается в доступе к рабочему потоку, вы на самом деле не хотите создавать новый поток в каждом окне, поскольку для создания каждого рабочего потока требуются время и системные ресурсы.
В этом случае большое преимущество имеет возможность совместного использования одного рабочего потока между каждым окном из одного источника.
Ниже представлен простейший способ создания потока SharedWorker, который могут использовать несколько окон из одного источника:
// Window 1 var aSharedWorker = new SharedWorker("SharedWorker.js"); // Window 2 var aSharedWorker = new SharedWorker("SharedWorker.js");
// Window 1 var aSharedWorker = new SharedWorker("SharedWorker.js", "SharedWorkerName"); // Window 2 var aSharedWorker = new SharedWorker("SharedWorker.js", "SharedWorkerName");
Вот где вступает в действие второй параметр конструктора SharedWorker.
Вы можете создать несколько разных потоков SharedWorker, указав разные имена при создании рабочих объектов.
Ниже приведен пример двух окон, каждое из которых имеет два рабочих потока: «Рабочий1» и «Рабочий2»:
// Window 1 - Shared Worker 1 & 2 var aSharedWorker1 = new SharedWorker("SharedWorker.js", "Worker1"); var aSharedWorker2 = new SharedWorker("SharedWorker.js", "Worker2"); // Window 2 - Shared Worker 1 & 2 var aSharedWorker1 = new SharedWorker("SharedWorker.js", "Worker1"); var aSharedWorker2 = new SharedWorker("SharedWorker.js", "Worker2");
Когда речь идет о присвоении имен общим сотрудникам, важно знать, что имена чувствительны к регистру.
Если вы дадите одному работнику имя Worker1, а другому работнику — имя worker1, они могут выглядеть одинаково, но разница в регистре с ‘ w ‘ приводит к созданию двух рабочих потоков, а не просто созданию и повторному использованию одного рабочего потока.
Что вас может заинтересовать, так это то, что происходит, когда окно, в котором был создан общий работник, закрыто? Рабочий поток все еще доступен другим окнам из того же источника?
Окно 1 создает общего работника, и Окно 2 подключается к нему.Позже Окно 1 закрывается, но, поскольку Окно 2 все еще подключено, общий рабочий поток остается, даже если Окно 2 изначально не создавало его.
К счастью, рабочие потоки имеют доступ к глобальной функции importScripts, которая позволяет вам перетаскивать необходимые файлы JavaScript в область рабочего потока.
Если указано несколько файлов, они загружаются параллельно, но будут загружаться и обрабатываться синхронно в указанном порядке.
Ниже приведены некоторые примеры использования функции importScripts:
// Import just one file importScripts("file.js"); // Import multiple files with one call (careful // of their order if they have global variables // that depend on other js files being included // in the request...the JS files will be // downloaded in parallel but loaded and // processed synchronously based on their order // here). // Note: I stopped at 3 files to import but you // can include any amount importScripts("file1.js", "file2.js", "file3.js");
Технически, спецификация W3C позволяет использовать функцию importScripts без параметров, но это не имеет никакого эффекта.
В моем предыдущем посте я показал следующий метод присоединения к событию onmessage общего рабочего (в ветке):
onconnect = function (evt) { var port = evt.ports[0]; port.onmessage = function (e) { OnControllerMessage(e, port); } } function OnControllerMessage(e, port) { var sReturnMessage = ("Hello from the sharedworker thread!...This is what you sent my way: " + e.data); port.postMessage(sReturnMessage); }
Я немного покопался и нашел обходной путь, позволяющий избежать необходимости замыканий, используя свойство target объекта события. В этом случае целевым свойством является порт.
В следующем примере демонстрируется подключение к событию onmessage и отправка данных обратно вызывающей стороне через свойство target события:
onconnect = function (evt) { evt.ports[0].onmessage = OnControllerMessage; } function OnControllerMessage(e) { var sReturnMessage = ("Hello from the sharedworker thread!...This is what you sent my way: " + e.data); e.target.postMessage(sReturnMessage); }
Рабочие потоки поддерживают тайм-ауты (setTimeout, clearTimeout, setInterval и clearInterval), что полезно, если вы хотите обрабатывать информацию только через заданные интервалы, а не постоянно обрабатывать.
Один из сценариев, который приходит на ум, может быть, если вам нужно проверить наличие обновлений со стороннего сайта и вы не хотите постоянно забивать сайт запросами.
Вы можете настроить таймер для проверки сайта каждые пять минут или около того, и, если доступна новая информация, передать ее на уровень пользовательского интерфейса, чтобы ее можно было включить в информацию отображения.
Объект XMLHttpRequest может использоваться в рабочем потоке и может использоваться синхронно или асинхронно. Это полностью зависит от вас, если вы используете его асинхронно, так как рабочий поток уже отделен от потока пользовательского интерфейса, поэтому ожидание синхронного возврата не повредит отзывчивости пользовательского интерфейса.
Что следует знать об использовании объекта XMLHttpRequest из рабочего потока, так это то, что свойство responseXML всегда будет нулевым.
Возвращаемые данные из XMLHttpRequest, находящиеся в рабочем потоке, всегда будут находиться в свойстве responseText, как показано в следующем примере:
var xhrRequest = new XMLHttpRequest(); xhrRequest.open("GET", sURL, false); xhrRequest.send(); return xhrRequest.responseText;
Здесь есть некоторые отличия браузера:
- Chrome 5 и Safari 5 просто передают ошибку в виде строки в обработчик ошибок в потоке
- Firefox 3.6.8 и 4.0 beta 2 передают объект ErrorEvent обработчику ошибок в потоке
Атрибуты объекта ErrorEvent:
- message — удобочитаемое сообщение об ошибке
- filename — имя файла скрипта, в котором произошла ошибка
- lineno — номер строки файла скрипта, в котором произошла ошибка
Ниже приведен пример присоединения к событию onerror выделенного рабочего потока (этот пример также будет работать для совместно используемых рабочих, за исключением того, что для совместно используемых рабочих необходимо вызывать postMessage через порт):
// Attach to the global error handler of the // thread onerror = OnErrorHandler; function OnErrorHandler(e) { // In Chrome 5/Safari 5, 'e' is a string for // both dedicated and shared workers within // the thread if (typeof (e) == "string") { postMessage("Error Message: " + e); } else // Dedicated worker in Firefox...(Firefox // does not yet support shared workers) { postMessage("Error Message: " + e.message + " File Name: " + e.filename + " Line Number: " + e.lineno); } } // to test the error handler, throw an error throw "This is a test error";
Все браузеры (Chrome 5, Safari 5, Firefox 3.6.8 / 4.0 beta 2) реализуют событие ошибки выделенного рабочего экземпляра одинаково, передавая объект ErrorEvent.
Однако, когда дело доходит до общих работников, я не смог получить экземпляр объекта общего рабочего, чтобы вызвать событие onerror в Chrome 5 или Safari 5. Из моего исследования выяснилось, что для общих работников событие onerror будет вызвано только для общего рабочего экземпляра, если во время создания рабочего потока произошла сетевая ошибка.
Ниже приведен пример подключения к событию onerror выделенного рабочего экземпляра (вы настраиваете общий рабочий точно так же):
var aWorker = new Worker("DedicatedWorker.js"); aWorker.onerror = OnErrorMsg; function OnErrorMsg(e) { alert("Error Message: " + e.message + " File Name: " + e.filename + " Line Number: " + e.lineno); }
Создатель работника может закрыть поток, вызвав ‘terminate’ на экземпляре работника, как в следующем примере:
var aDedicatedWorker = new Worker("DedicatedWorker.js"); ... // We're done with the tread so let the // browser release the system resources aDedicatedWorker.terminate();
// JavaScript of the thread itself ... close();
If you would like more information on the HTML 5 Web Workers specification you can click on the following links:
http://www.whatwg.org/specs/web-workers/current-work/
http://www.w3.org/TR/workers/
Source: http://cggallant.blogspot.com/2010/08/deeper-look-at-html-5-web-workers.html