Web Worker-Ñ Ð¿ÑедоÑÑавлÑÑÑ Ð¿ÑоÑÑое ÑÑедÑÑво Ð´Ð»Ñ Ð·Ð°Ð¿ÑÑка ÑкÑипÑов в Ñоновом поÑоке. ÐоÑок Worker'а Ð¼Ð¾Ð¶ÐµÑ Ð²ÑполнÑÑÑ Ð·Ð°Ð´Ð°Ñи без вмеÑаÑелÑÑÑва в полÑзоваÑелÑÑкий инÑеÑÑейÑ. Ð ÑÐ¾Ð¼Ñ Ð¶Ðµ, они могÑÑ Ð¾ÑÑÑеÑÑвлÑÑÑ Ð²Ð²Ð¾Ð´/вÑвод, иÑполÑзÑÑ XMLHttpRequest
(Ñ
оÑÑ Ð°ÑÑибÑÑÑ responseXML
и channel
вÑегда бÑдÑÑ ÑÐ°Ð²Ð½Ñ null). СÑÑеÑÑвÑÑÑий Worker Ð¼Ð¾Ð¶ÐµÑ Ð¾ÑÑÑлаÑÑ ÑообÑÐµÐ½Ð¸Ñ JavaScript кодÑ-ÑоздаÑÐµÐ»Ñ ÑеÑез обÑабоÑÑик ÑобÑÑий, ÑказаннÑй ÑÑим кодом (и наобоÑоÑ). ÐÑа ÑÑаÑÑÑ Ð´Ð°ÑÑ Ð´ÐµÑалÑнÑÑ Ð¸Ð½ÑÑÑÑкÑÐ¸Ñ Ð¿Ð¾ иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Web Workers.
Worker - ÑÑо обÑекÑ, ÑоздаваемÑй конÑÑÑÑкÑоÑом (напÑимеÑ, Worker()
) и запÑÑкаÑÑий именной JavaScript Ñайл â ÑÑÐ¾Ñ Ñайл ÑодеÑÐ¶Ð¸Ñ ÐºÐ¾Ð´, коÑоÑÑй бÑÐ´ÐµÑ Ð²Ñполнен в поÑоке Worker'а; обÑекÑÑ Ð¶Ðµ Workers запÑÑкаÑÑÑÑ Ð² дÑÑгом глобалÑном конÑекÑÑе, оÑлиÑаÑÑемÑÑ Ð¾Ñ ÑекÑÑего, - window
. ÐоÑÑÐ¾Ð¼Ñ Ð¸ÑполÑзование пеÑеменной window
Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ ÑекÑÑего глобалÑного конÑекÑÑа (вмеÑÑо self
) внÑÑÑи Worker
веÑнÑÑ Ð¾ÑибкÑ.
ÐонÑекÑÑ Worker'а пÑедÑÑавлен обÑекÑом DedicatedWorkerGlobalScope
в ÑлÑÑае вÑделеннÑÑ
Workers (обÑÑнÑе Workers иÑполÑзÑÑÑÑÑ Ð¾Ð´Ð½Ð¸Ð¼ ÑкÑипÑом; ÑовмеÑÑнÑе Workers иÑполÑзÑÑÑ Ð¾Ð±ÑÐµÐºÑ SharedWorkerGlobalScope
). ÐÑделеннÑй Worker доÑÑÑпен ÑолÑко из ÑкÑипÑа-ÑодиÑелÑ, в Ñо вÑÐµÐ¼Ñ ÐºÐ°Ðº ÑовмеÑÑнÑе Workers могÑÑ Ð±ÑÑÑ Ð´Ð¾ÑÑÑÐ¿Ð½Ñ Ð¸Ð· неÑколÑкиÑ
ÑÑенаÑиев.
ÐÑимеÑание: СмоÑÑиÑе ÑÑÑаниÑÑ Web Workers API Ð´Ð»Ñ ÑпÑавки по Workers и пÑоÑие ÑÑководÑÑва.
ÐÑ Ð¼Ð¾Ð¶ÐµÑе запÑÑкаÑÑ Ð»Ñбой код внÑÑÑи поÑока worker-а, за некоÑоÑÑми иÑклÑÑениÑми. ÐапÑимеÑ, Ð²Ñ Ð½Ðµ можеÑе пÑÑмо манипÑлиÑоваÑÑ DOM внÑÑÑи worker-а, или иÑполÑзоваÑÑ Ð½ÐµÐºÐ¾ÑоÑÑе меÑÐ¾Ð´Ñ Ð¿Ð¾ ÑмолÑÐ°Ð½Ð¸Ñ Ð¸ ÑвойÑÑва обÑекÑа window
. Ðо Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе иÑполÑзоваÑÑ Ð±Ð¾Ð»ÑÑой Ð½Ð°Ð±Ð¾Ñ Ð¾Ð¿Ñий, доÑÑÑпнÑй под Window
, вклÑÑÐ°Ñ WebSockets, и меÑ
Ð°Ð½Ð¸Ð·Ð¼Ñ Ñ
ÑÐ°Ð½ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
, ÑакиÑ
как IndexedDB и оÑноÑÑÑиÑ
ÑÑ ÑолÑко к Firefox OS Data Store API. ÐÐ»Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑной инÑоÑмаÑии ÑмоÑÑиÑе Functions and classes available to workers.
ÐаннÑе пеÑедаÑÑÑÑ Ð¼ÐµÐ¶Ð´Ñ worker-ами и главнÑм поÑоком ÑеÑез ÑиÑÑÐµÐ¼Ñ ÑообÑений â обе ÑÑоÑÐ¾Ð½Ñ Ð¿ÐµÑедаÑÑ Ñвои ÑообÑениÑ, иÑполÑзÑÑ Ð¼ÐµÑод postMessage()
и оÑвеÑаÑÑ Ð½Ð° ÑообÑÐµÐ½Ð¸Ñ Ð¿Ñи помоÑи обÑабоÑÑика ÑобÑÑий onmessage
(ÑообÑение Ñ
ÑаниÑÑÑ Ð² аÑÑибÑÑе data ÑобÑÑÐ¸Ñ Message
). ÐаннÑе пÑи ÑÑом копиÑÑÑÑÑÑ, а не делÑÑÑÑ.
ÐбÑекÑÑ Workers могÑÑ, в ÑÐ²Ð¾Ñ Ð¾ÑеÑедÑ, ÑоздаваÑÑ Ð½Ð¾Ð²Ñе обÑекÑÑ workers, и Ñак до ÑеÑ
поÑ, пока вÑÑ ÑабоÑÐ°ÐµÑ Ð² ÑамкаÑ
ÑекÑÑей ÑÑÑаниÑÑ. ÐлÑÑ Ðº ÑÑомÑ, обÑекÑÑ workers могÑÑ Ð¸ÑполÑзоваÑÑ XMLHttpRequest
Ð´Ð»Ñ ÑеÑевого ввода/вÑвода, но еÑÑÑ Ð¸ÑклÑÑение - аÑÑибÑÑÑ responseXML
и channel
обÑекÑа XMLHttpRequest
вÑегда возвÑаÑаÑÑ null
.
Ðак Ñже ÑпоминалоÑÑ Ð²ÑÑе, вÑделеннÑй Worker доÑÑÑпен ÑолÑко Ð´Ð»Ñ ÑкÑипÑа, коÑоÑÑй его вÑзвал. Ð ÑÑом Ñазделе ÑеÑÑ Ð¿Ð¾Ð¹Ð´ÑÑ Ð¾ JavaScript, коÑоÑÑй можно найÑи в наÑем оÑновном пÑимеÑе вÑделенного Worker (запÑÑÑиÑÑ ÑкÑипÑ): ÑÑÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ð¿Ð¾Ð·Ð²Ð¾Ð»ÑÐµÑ Ð²Ð²ÐµÑÑи два ÑиÑла Ð´Ð»Ñ ÑмножениÑ. ÐÑи ÑиÑла оÑпÑавлÑÑÑÑÑ Ð² Worker, пеÑемножаÑÑÑÑ, а ÑезÑлÑÑÐ°Ñ Ð²Ð¾Ð·Ð²ÑаÑаеÑÑÑ Ð½Ð° ÑÑÑаниÑÑ Ð¸ оÑобÑажаеÑÑÑ.
ÐÑÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ð´Ð¾ÑÑаÑоÑно ÑÑивиален, но Ð´Ð»Ñ Ð¾Ð·Ð½Ð°ÐºÐ¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ Ð±Ð°Ð·Ð¾Ð²Ñми конÑепÑиÑми worker-ов Ð¼Ñ ÑеÑили его ÑпÑоÑÑиÑÑ. Ðолее пÑодвинÑÑÑе деÑали опиÑÐ°Ð½Ñ Ð´Ð°Ð»ÐµÐµ в ÑÑаÑÑе.
ÐпÑеделение поддеÑжки WorkerÐÐ»Ñ Ð±Ð¾Ð»ÑÑего конÑÑÐ¾Ð»Ñ Ð½Ð°Ð´ оÑибками и обÑаÑной ÑовмеÑÑимоÑÑи, ÑекомендÑеÑÑÑ Ð¾Ð±ÐµÑнÑÑÑ Ð²Ð°Ñ ÐºÐ¾Ð´ доÑÑÑпа к worker-Ñ Ð² ÑледÑÑÑий (main.js):
if (window.Worker) {
...
}
Создание вÑделенного worker
Создание нового worker-а â ÑÑо легко. ÐÑÑ ÑÑо вам нÑжно ÑÑо вÑзваÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¾Ñ Worker()
, Ñказав URI ÑкÑипÑа Ð´Ð»Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð² поÑоке worker-а (main.js):
var myWorker = new Worker("worker.js");
ÐеÑедаÑа ÑообÑений в и из вÑделенного worker
ÐÐ°Ð³Ð¸Ñ worker-ов пÑоиÑÑ
Ð¾Ð´Ð¸Ñ ÑеÑез postMessage()
меÑод и обÑабоÑÑик ÑобÑÑий onmessage
. Ðогда Ð²Ñ Ñ
оÑиÑе оÑпÑавиÑÑ ÑообÑение в worker, Ð²Ñ Ð´Ð¾ÑÑавлÑеÑе ÑообÑение к Ð½ÐµÐ¼Ñ Ð²Ð¾Ñ Ñак (main.js):
first.onchange = function () {
myWorker.postMessage([first.value, second.value]);
console.log("Message posted to worker");
};
second.onchange = function () {
myWorker.postMessage([first.value, second.value]);
console.log("Message posted to worker");
};
РпÑиведÑнном ÑÑагменÑе кода Ð¼Ñ Ð¸Ð¼ÐµÐµÐ¼ два <input>
ÑлеменÑа, пÑедÑÑавленнÑÑ
пеÑеменнÑми first
и second
; когда знаÑение лÑбой из пеÑеменнÑÑ
изменÑеÑÑÑ, myWorker.postMessage([first.value,second.value])
иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð¾ÑпÑавки обоиÑ
знаÑений, пÑедÑÑавленнÑÑ
в виде маÑÑива, в worker. ÐоÑÑедÑÑвом аÑгÑменÑа message
возможна пеÑедаÑа пÑакÑиÑеÑки лÑбÑÑ
даннÑÑ
в worker.
ÐнÑÑÑи worker-a Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ обÑабаÑÑваÑÑ ÑообÑÐµÐ½Ð¸Ñ Ð¸ оÑвеÑаÑÑ Ð½Ð° ниÑ
пÑи помоÑи Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±ÑабоÑÑика ÑобÑÑÐ¸Ñ onmessage
подобнÑм обÑазом (worker.js):
onmessage = function (e) {
console.log("Message received from main script");
var workerResult = "Result: " + e.data[0] * e.data[1];
console.log("Posting message back to main script");
postMessage(workerResult);
};
ÐбÑабоÑÑик onmessage
позволÑÐµÑ Ð½Ð°Ð¼ запÑÑÑиÑÑ Ð½ÐµÐºÐ¸Ð¹ код вÑÑкий Ñаз, когда полÑÑен Ð¿Ð°ÐºÐµÑ Ñ ÑообÑением, доÑÑÑпнÑм в аÑÑибÑÑе data
ÑобÑÑÐ¸Ñ message
. РпÑимеÑе вÑÑе Ð¼Ñ Ð¿ÑоÑÑо пеÑемножаем вмеÑÑе две ÑиÑÑÑ, поÑле Ñего иÑполÑзÑем postMessage()
Ñнова, ÑÑÐ¾Ð±Ñ Ð¾ÑпÑавиÑÑ Ð¿Ð¾Ð»ÑÑеннÑй ÑезÑлÑÑÐ°Ñ Ð½Ð°Ð·Ð°Ð´ в оÑновной поÑок.
ÐозвÑаÑаÑÑÑ Ð² оÑновной поÑок, Ð¼Ñ Ð¸ÑполÑзÑем onmessage
Ñнова, ÑÑÐ¾Ð±Ñ Ð¾ÑÑеагиÑоваÑÑ Ð½Ð° ÑообÑение, оÑпÑавленное нам назад из worker-а:
myWorker.onmessage = function (e) {
result.textContent = e.data;
console.log("Message received from worker");
};
РпÑимеÑе вÑÑе Ð¼Ñ Ð±ÐµÑÑм даннÑе из ÑобÑÑÐ¸Ñ ÑообÑÐµÐ½Ð¸Ñ Ð¸ ÑÑавим иÑ
как textContent
Ñ ÑезÑлÑÑиÑÑÑÑего абзаÑа, ÑÑÐ¾Ð±Ñ Ð¿Ð¾ÐºÐ°Ð·Ð°ÑÑ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ ÑезÑлÑÑÐ°Ñ ÑÑой калÑкÑлÑÑии.
ÐÑимеÑание: ÐбÑаÑиÑе внимание, ÑÑо onmessage()
и postmessage()
Ð´Ð¾Ð»Ð¶Ð½Ñ Ð²ÑзÑваÑÑÑÑ Ð¸Ð· ÑкземплÑÑа Worker в главном поÑоке, но не в поÑоке worker-а. ÐÑо ÑвÑзано Ñ Ñем, ÑÑо внÑÑÑи поÑока worker-а, worker вÑÑÑÑÐ¿Ð°ÐµÑ Ð² каÑеÑÑве глобалÑного обÑекÑа.
ÐÑимеÑание: ÐÑи пеÑедаÑе ÑообÑÐµÐ½Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñ Ð¾ÑновнÑм поÑоком и поÑоком worker-а, оно копиÑÑеÑÑÑ Ð¸Ð»Ð¸ "пеÑедаÑÑÑÑ" (пеÑемеÑаеÑÑÑ), не делиÑÑÑ Ð¼ÐµÐ¶Ð´Ñ Ð¿Ð¾Ñоками. ЧиÑайÑе Transferring data to and from workers: further details Ð´Ð»Ñ Ð±Ð¾Ð»ÐµÐµ подÑобного обÑÑÑнениÑ.
ÐавеÑÑение ÑабоÑÑ worker-аÐÑекÑаÑение ÑабоÑÑ worker-а главного поÑока доÑÑигаеÑÑÑ Ð¼ÐµÑодом terminate
:
ÐоÑок worker-а немедленно ÑниÑÑожаеÑÑÑ.
ÐбÑабоÑка оÑибокÐÑи оÑибке во вÑÐµÐ¼Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ worker-а, вÑзÑваеÑÑÑ ÐµÐ³Ð¾ обÑабоÑÑик ÑобÑÑий onerror
. Ðн пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ ÑобÑÑие error
, коÑоÑое ÑеализÑÐµÑ Ð¸Ð½ÑеÑÑÐµÐ¹Ñ ErrorEvent
.
СобÑÑие не вÑплÑÐ²Ð°ÐµÑ Ð¸ его можно оÑмениÑÑ. ÐÐ»Ñ Ð¾ÑÐ¼ÐµÐ½Ñ Ð´ÐµÐ¹ÑÑÐ²Ð¸Ñ Ð¿Ð¾ ÑмолÑаниÑ, worker Ð¼Ð¾Ð¶ÐµÑ Ð²ÑзваÑÑ Ð¼ÐµÑод preventDefault()
в обÑабоÑÑике ÑобÑÑÐ¸Ñ Ð¾Ñибки.
У ÑобÑÑÐ¸Ñ Ð¾Ñибки еÑÑÑ ÑÑи полÑ, коÑоÑÑе пÑедÑÑавлÑÑÑ Ð¸Ð½ÑеÑеÑ:
message
СообÑение об оÑибке в ÑиÑаемом виде.
filename
ÐÐ¼Ñ Ñайла Ñо ÑкÑипÑом, в коÑоÑом оÑибка пÑоизоÑла.
lineno
ÐÐ¾Ð¼ÐµÑ ÑÑÑоки в Ñайле, в коÑоÑом пÑоизоÑла оÑибка.
Worker-Ñ Ð¼Ð¾Ð³ÑÑ Ð·Ð°Ð¿ÑÑкаÑÑ Ð´ÑÑгие worker-Ñ. Так назÑваемÑе sub-worker'Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ñого же пÑоиÑÑ Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ (same-origin), ÑÑо и ÑодиÑелÑÑкий докÑменÑ. ÐÑоме Ñого, URI Ð´Ð»Ñ subworker-ов ÑаÑÑÑиÑÑваÑÑÑÑ Ð¾ÑноÑиÑелÑно ÑодиÑелÑÑкого worker'а, а не ÑодиÑелÑÑкого докÑменÑа. ÐÑо позволÑÐµÑ worker-ам пÑоÑе ÑледиÑÑ Ð·Ð° Ñем, где Ð½Ð°Ñ Ð¾Ð´ÑÑÑÑ Ð¸Ñ Ð·Ð°Ð²Ð¸ÑимоÑÑи.
ÐмпоÑÑ ÑкÑипÑов и библиоÑекWorker поÑоки имеÑÑ Ð´Ð¾ÑÑÑп к глобалÑной ÑÑнкÑии, importScripts()
, коÑоÑÐ°Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»ÑÐµÑ Ð¸Ð¼Ð¿Ð¾ÑÑиÑоваÑÑ ÑкÑипÑÑ Ñ Ñого же домена в иÑ
облаÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи. ФÑнкÑÐ¸Ñ Ð¿ÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð½Ð¾Ð»Ñ Ð¸ более URI паÑамеÑÑов, как ÑпиÑок ÑÑÑлок на ÑеÑÑÑÑÑ Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾ÑÑа; вÑе нижепÑиведÑннÑе пÑимеÑÑ Ð²ÐµÑнÑ:
importScripts(); /* imports nothing */
importScripts("foo.js"); /* imports just "foo.js" */
importScripts("foo.js", "bar.js"); /* imports two scripts */
ÐÑаÑÐ·ÐµÑ Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÑ ÐºÐ°Ð¶Ð´Ñй ÑказаннÑй ÑкÑÐ¸Ð¿Ñ Ð¸ иÑполнÑÐµÑ ÐµÐ³Ð¾. ÐÑбÑе глобалÑнÑе обÑекÑÑ, ÑоздаваемÑе каждÑм ÑкÑипÑом могÑÑ Ð±ÑÑÑ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ñ Ð² worker'е. ÐÑли ÑкÑÐ¸Ð¿Ñ Ð½Ðµ ÑдалоÑÑ Ð·Ð°Ð³ÑÑзиÑÑ, бÑÐ´ÐµÑ Ð±ÑоÑена оÑибка NETWORK_ERROR
, и поÑледÑÑÑий код не бÑÐ´ÐµÑ Ð¸Ñполнен. Тем не менее код, иÑполненнÑй Ñанее (вклÑÑÐ°Ñ Ð¾ÑложеннÑй пÑи помоÑи window.setTimeout()
) оÑÑанеÑÑÑ ÑÑнкÑионален. ÐбÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÑÑнкÑий идÑÑие поÑле вÑзова меÑода importScripts()
Ñакже бÑдÑÑ Ð´Ð¾ÑÑÑпнÑ, Ñ.к. обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÑÑнкÑий вÑегда обÑабаÑÑваÑÑÑÑ Ð¿ÐµÑед оÑÑалÑнÑм кодом.
ÐÑимеÑание: СкÑипÑÑ Ð¼Ð¾Ð³ÑÑ Ð±ÑÑÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐ½Ñ Ð² пÑоизволÑном поÑÑдке, но иÑ
иÑполнение бÑÐ´ÐµÑ Ð² Ñом поÑÑдке, в коÑоÑом имена Ñайлов бÑли пеÑÐµÐ´Ð°Ð½Ñ Ð² importScripts()
. ФÑнкÑÐ¸Ñ Ð²ÑполнÑеÑÑÑ ÑинÑ
Ñонно; importScripts()
не веÑнÑÑ Ð¸Ñполнение, пока вÑе ÑкÑипÑÑ Ð½Ðµ бÑдÑÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐ½Ñ Ð¸ иÑполненÑ.
РазделÑемÑй worker доÑÑÑпен неÑколÑким ÑазнÑм ÑкÑипÑам â даже еÑли они Ð½Ð°Ñ Ð¾Ð´ÑÑÑÑ Ð² ÑазнÑÑ Ð¾ÐºÐ½Ð°Ñ , ÑÑÐµÐ¹Ð¼Ð°Ñ Ð¸Ð»Ð¸ даже worker-Ð°Ñ . Ð ÑÑом Ñазделе Ð¼Ñ Ð¾Ð±ÑÑдим JavaScript, коÑоÑÑй можно найÑи в наÑем базовом пÑимеÑе ÑазделÑемÑÑ worker-ов (запÑÑÑиÑÑ ÑазделÑемÑй worker): Ðн оÑÐµÐ½Ñ Ð¿Ð¾Ñ Ð¾Ð¶ на базовÑй пÑÐ¸Ð¼ÐµÑ Ð²ÑделеннÑÑ worker-ов, за иÑклÑÑением двÑÑ ÑÑнкÑий, коÑоÑÑе доÑÑÑÐ¿Ð½Ñ Ð¸Ð· ÑазнÑÑ ÑкÑипÑовÑÑ Ñайлов: Ñмножение двÑÑ ÑиÑел или возведение ÑиÑла в ÑÑепенÑ. Ðба ÑкÑипÑа иÑполÑзÑÑÑ Ð¾Ð´Ð¸Ð½ и ÑÐ¾Ñ Ð¶Ðµ worker Ð´Ð»Ñ Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼ÑÑ Ð²ÑÑиÑлений.
ÐдеÑÑ Ð¼Ñ ÑоÑÑедоÑоÑимÑÑ Ð½Ð° ÑазниÑе Ð¼ÐµÐ¶Ð´Ñ Ð²ÑделеннÑми и ÑазделÑннÑми worker-ами. ÐбÑаÑиÑе внимание, ÑÑо в данном пÑимеÑе еÑÑÑ Ð´Ð²Ðµ HTML ÑÑÑаниÑÑ Ñ JavaScript-кодом, коÑоÑÑе иÑполÑзÑÑÑ Ð¾Ð´Ð¸Ð½ и ÑÐ¾Ñ Ð¶Ðµ Ñайл worker-а.
ÐÑимеÑание: ÐÑли ÑазделÑемÑй worker Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð´Ð¾ÑÑÑпен из неÑколÑÐºÐ¸Ñ ÐºÐ¾Ð½ÑекÑÑов пÑоÑмоÑÑа, Ñо вÑе они Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¸Ð¼ÐµÑÑ Ð¾Ð´Ð½Ð¾ и Ñо же пÑоиÑÑ Ð¾Ð¶Ð´ÐµÐ½Ð¸Ðµ (одни и Ñе же пÑоÑокол, Ñ Ð¾ÑÑ Ð¸ поÑÑ).
Создание ÑазделÑемого worker-а**ÐÑимеÑание:**Ð Firefox ÑазделÑемÑй worker не Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸ÑполÑзован ÑовмеÑÑно докÑменÑами в пÑиваÑном и непÑиваÑном окне (Firefox bug 1177621).
ÐапÑÑк ÑазделÑемого worker-а оÑÐµÐ½Ñ Ð¿Ð¾Ñ Ð¾Ð¶ на запÑÑк вÑделенного worker-а, но иÑполÑзÑеÑÑÑ Ð´ÑÑгой конÑÑÑÑкÑÐ¾Ñ (Ñм. index.html и index2.html) â в каждом докÑменÑе Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ поднÑÑÑ worker, Ð´Ð»Ñ ÑÑого ÑледÑÐµÑ Ð½Ð°Ð¿Ð¸ÑаÑÑ Ñакой код:
var myWorker = new SharedWorker("worker.js");
ÐолÑÑÐ°Ñ ÑазниÑа заклÑÑаеÑÑÑ Ð² Ñом, ÑÑо Ñ ÑазделÑемÑм worker-ом необÑ
одимо взаимодейÑÑвоваÑÑ ÑеÑез обÑÐµÐºÑ port
â Ñвно оÑкÑÑв поÑÑ, Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÐºÐ¾ÑоÑого ÑкÑипÑÑ Ð¼Ð¾Ð³ÑÑ Ð²Ð·Ð°Ð¸Ð¼Ð¾Ð´ÐµÐ¹ÑÑвоваÑÑ Ñ worker-ом (в ÑлÑÑае вÑделенного worker-а ÑÑо пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð½ÐµÑвно).
Соединение Ñ Ð¿Ð¾ÑÑом должно бÑÑÑ Ð¾ÑÑÑеÑÑвлено либо неÑвно, иÑполÑзÑÑ Ð¾Ð±ÑабоÑÑик ÑобÑÑие onmessage
, либо Ñвно, вÑзвав меÑод start() пеÑед Ñем, как оÑпÑавлÑÑÑ Ð»ÑбÑе ÑообÑениÑ. ÐÑзов меÑода start() необÑ
одим ÑолÑко Ñогда, когда подпиÑка на ÑобÑÑие Ñеализована ÑеÑез меÑод addEventListener()
.
**ÐÑимеÑание:**Ðогда иÑполÑзÑеÑÑÑ Ð¼ÐµÑод
start()
ÑÑÐ¾Ð±Ñ Ð¾ÑкÑÑÑÑ Ñоединение Ñ Ð¿Ð¾ÑÑом, его Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ вÑзÑваÑÑ Ð¸ в ÑодиÑелÑÑком поÑоке и в поÑоке worker-а, еÑли Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð° двÑÑ ÑÑоÑоннÑÑ ÐºÐ¾Ð¼Ð¼ÑникаÑиÑ.
myWorker.port.start(); // в ÑодиÑелÑÑком поÑоке
port.start(); // в поÑоке worker-а, где пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ port ÑвлÑеÑÑÑ ÑÑÑлкой на поÑÑ
ÐеÑедаÑа ÑообÑений в/из ÑазделÑемого worker-а
ТепеÑÑ ÑообÑÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑÑ Ð±ÑÑÑ Ð¾ÑпÑÐ°Ð²Ð»ÐµÐ½Ñ worker-Ñ, как и пÑежде, но меÑод postMessage()
должен вÑзÑваÑÑÑÑ Ð¸Ð· обÑекÑа port
(еÑÑ Ñаз, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑвидеÑÑ ÑÑ
ожие конÑÑÑÑкÑии в multiply.js и square.js):
squareNumber.onchange = function () {
myWorker.port.postMessage([squareNumber.value, squareNumber.value]);
console.log("Message posted to worker");
};
ТепеÑÑ Ð½Ð° ÑÑоÑоне worker-а. ÐдеÑÑ ÐºÐ¾Ð´ немного Ñложнее (worker.js):
self.addEventListener("connect", function (e) {
// ÑÑебÑеÑÑÑ addEventListener()
var port = e.ports[0];
port.onmessage = function (e) {
var workerResult = "Result: " + e.data[0] * e.data[1];
port.postMessage(workerResult);
};
port.start(); // вÑзов необÑзаÑелÑнÑй, Ñ.к. иÑполÑзÑеÑÑÑ Ð¾Ð±ÑабоÑÑик ÑобÑÑий onmessage
});
ÐеÑвÑй ÑÑап ÑоÑÑÐ¾Ð¸Ñ Ð¸Ð· ÑобÑÑÐ¸Ñ onconnect
. Ðно ÑÑабаÑÑваеÑ, когда пÑоизоÑло подклÑÑение (Ñ.е. когда в ÑодиÑелÑÑком поÑоке оÑÑабоÑало ÑобÑÑие onmessage
или когда в нем бÑл вÑзван меÑод start()
).
ÐÑ Ð¸ÑполÑзÑем аÑÑибÑÑ ÑобÑÑÐ¸Ñ ports
, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð¿Ð¾ÑÑ Ð¸ ÑоÑ
ÑаниÑÑ ÐµÐ³Ð¾ в пеÑеменной.
ÐÑоÑой ÑÑап â ÑÑо обÑабоÑÑик ÑобÑÑÐ¸Ñ message
на ÑоÑ
ÑанÑнном поÑÑÑ. Ðн нÑжен Ð´Ð»Ñ Ð¿Ð¾Ð´ÑÑÑÑа и вÑвода ÑезÑлÑÑаÑа вÑÑиÑÐ»ÐµÐ½Ð¸Ñ Ð² оÑновной поÑок. УÑÑановка обÑабоÑÑика message
в поÑоке worker-а Ñакже оÑкÑÑÐ²Ð°ÐµÑ Ð¿Ð¾Ð´ÐºÐ»ÑÑение к ÑодиÑелÑÑÐºÐ¾Ð¼Ñ Ð¿Ð¾ÑокÑ, поÑÑÐ¾Ð¼Ñ Ð²Ñзов на port.start()
на Ñамом деле не нÑжен (Ñм. код обÑабоÑÑика onconnect
).
ÐоÑледний ÑÑап â возвÑаÑение в оÑновной поÑок и обÑабоÑка ÑообÑÐµÐ½Ð¸Ñ Ð¾Ñ workerâа (еÑÑ Ñаз, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑвидеÑÑ ÑÑ Ð¾Ð¶Ð¸Ðµ конÑÑÑÑкÑии в multiply.js и square.js):
myWorker.port.onmessage = function (e) {
result2.textContent = e.data[0];
console.log("Message received from worker");
};
Ðогда ÑообÑение пÑÐ¸Ñ Ð¾Ð´Ð¸Ñ ÑеÑез поÑÑ Ð¾Ñ worker-а, Ð¼Ñ Ð¿ÑовеÑÑем Ñип ÑезÑлÑÑаÑа вÑÑиÑлений и заÑем вÑÑавлÑем его в ÑооÑвеÑÑÑвÑÑÑий абзаÑ.
РпоÑоковой безопаÑноÑÑиÐнÑеÑÑÐµÐ¹Ñ Worker
ÑоздаÑÑ Ð½Ð°ÑÑоÑÑие поÑоки на ÑÑовне опеÑаÑионной ÑиÑÑемÑ, ÑÑо Ð¼Ð¾Ð¶ÐµÑ ÑмÑÑиÑÑ Ð¾Ð¿ÑÑнÑÑ
пÑогÑаммиÑÑов и навеÑÑи иÑ
на мÑÑли о пÑоблемаÑ
, ÑвÑзаннÑÑ
Ñ ÐºÐ¾Ð½ÑликÑом доÑÑÑпа к обÑим обÑекÑам.
Ðа Ñамом деле ÑоздаÑÑ Ñакие пÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð´Ð¾ÑÑаÑоÑно Ñложно, Ñак как worker-Ñ Ð¶ÑÑÑко конÑÑолиÑÑÑÑÑÑ. У Ð½Ð¸Ñ Ð½ÐµÑ Ð´Ð¾ÑÑÑпа к непоÑокобезопаÑнÑм обÑекÑам DOM, а вÑе даннÑе Ð¼ÐµÐ¶Ð´Ñ Ð¿Ð¾Ñоками пеÑедаÑÑÑÑ Ð² каÑеÑÑве ÑеÑиализованнÑÑ Ð¾Ð±ÑекÑов. ÐÑидÑÑÑÑ Ð¾ÑÐµÐ½Ñ Ð¿Ð¾ÑÑаÑаÑÑÑÑ, ÑÑÐ¾Ð±Ñ Ð²ÑзÑваÑÑ Ð¿ÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð¿Ð¾ÑокобезопаÑноÑÑи в ваÑем коде.
ÐеÑедаÑа даннÑÑ Ð² и из worker-ов: дÑÑгие деÑалиÐеÑедаÑа даннÑÑ Ð¼ÐµÐ¶Ð´Ñ Ð³Ð»Ð°Ð²Ð½Ð¾Ð¹ ÑÑÑаниÑей и worker-ом пÑоиÑÑ Ð¾Ð´Ð¸Ñ Ð¿ÑÑÑм копиÑованиÑ, а не пеÑедаÑи по ÑÑÑлке. ÐбÑекÑÑ ÑеÑиализÑÑÑÑÑ Ð¿Ñи пеÑедаÑе и заÑем деÑеÑиализÑÑÑÑÑ Ð½Ð° дÑÑгом конÑе. СÑÑаниÑа и worker не иÑполÑзÑÑÑ ÑовмеÑÑно одни и Ñе же ÑкземплÑÑÑ, Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑоздаÑÑÑÑ Ñвой. ÐолÑÑинÑÑво бÑаÑзеÑов ÑеализÑÑÑ ÑÑо ÑÑÑÑкÑÑÑиÑованнÑм клониÑованием (structured cloning).
ÐÐ»Ñ Ð¸Ð»Ð»ÑÑÑÑаÑии ÑÑого Ð¼Ñ Ñоздадим ÑÑнкÑÐ¸Ñ emulateMessage()
, коÑоÑÐ°Ñ Ð±ÑÐ´ÐµÑ Ð¸Ð¼Ð¸ÑиÑоваÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ знаÑениÑ, коÑоÑое клониÑÑеÑÑÑ, но не иÑполÑзÑеÑÑÑ ÑовмеÑÑно пÑи пеÑеÑ
оде Ð¾Ñ worker-а к главной ÑÑÑаниÑе или наобоÑоÑ.
function emulateMessage(vVal) {
return eval("(" + JSON.stringify(vVal) + ")");
}
// Tests
// test #1
var example1 = new Number(3);
console.log(typeof example1); // object
console.log(typeof emulateMessage(example1)); // number
// test #2
var example2 = true;
console.log(typeof example2); // boolean
console.log(typeof emulateMessage(example2)); // boolean
// test #3
var example3 = new String("Hello World");
console.log(typeof example3); // object
console.log(typeof emulateMessage(example3)); // string
// test #4
var example4 = {
name: "John Smith",
age: 43,
};
console.log(typeof example4); // object
console.log(typeof emulateMessage(example4)); // object
// test #5
function Animal(sType, nAge) {
this.type = sType;
this.age = nAge;
}
var example5 = new Animal("Cat", 3);
alert(example5.constructor); // Animal
alert(emulateMessage(example5).constructor); // Object
ÐнаÑениÑ, коÑоÑÑе клониÑÑÑÑÑÑ Ð¸ ÑовмеÑÑно не иÑполÑзÑÑÑÑÑ, назÑваÑÑÑÑ ÑообÑениÑми. Ðак вÑ, возможно, знаеÑе, ÑообÑÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑÑ Ð±ÑÑÑ Ð¾ÑпÑÐ°Ð²Ð»ÐµÐ½Ñ Ð² главнÑÑ ÑÑÑаниÑÑ Ð¸ из неÑ, иÑполÑзÑÑ postMessage()
, и data
, ÑодеÑжа даннÑе, пеÑедаваемÑе из worker-а.
example.html: (Ð³Ð»Ð°Ð²Ð½Ð°Ñ ÑÑÑаниÑа):
var myWorker = new Worker("my_task.js");
myWorker.onmessage = function (oEvent) {
console.log("Worker said : " + oEvent.data);
};
myWorker.postMessage("ali");
my_task.js (worker):
postMessage("I'm working before postMessage('ali').");
onmessage = function (oEvent) {
postMessage("Hi " + oEvent.data);
};
ÐлгоÑиÑм ÑÑÑÑкÑÑÑиÑованного клониÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑинÑÑÑ JSON и некоÑоÑÑе веÑи, коÑоÑÑе JSON не Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑинÑÑÑ, напÑимеÑ, ÑиклиÑеÑкие ÑÑÑлки.
ÐÑимеÑÑ Ð¿ÐµÑедаÑи даннÑÑ ÐÑÐ¸Ð¼ÐµÑ #1: РаÑÑиÑÐµÐ½Ð½Ð°Ñ Ð¿ÐµÑедаÑа JSON даннÑÑ Ð¸ Ñоздание ÑиÑÑÐµÐ¼Ñ ÐºÐ¾Ð¼Ð¼ÑÑаÑииÐÑли вам нÑжно пеÑедаÑÑ ÑложнÑе даннÑе и вÑзваÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑво ÑазлиÑнÑÑ ÑÑнкÑий как на главной ÑÑÑаниÑе, Ñак и в worker-е, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑоздаÑÑ ÑледÑÑÑÑÑ ÑиÑÑемÑ.
РпеÑвÑÑ Ð¾ÑеÑÐµÐ´Ñ Ð¼Ñ ÑоздаÑм клаÑÑ QueryableWorker, коÑоÑÑй пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ url worker-а, ÑÑандаÑÑнÑй обÑабоÑÑик ÑобÑÑий (defaultListener) и обÑабоÑÑик оÑибок. ÐÑÐ¾Ñ ÐºÐ»Ð°ÑÑ Ð±ÑÐ´ÐµÑ Ð¾ÑÑлеживаÑÑ Ð²ÑÐµÑ Ð¾Ð±ÑабоÑÑиков и Ð¿Ð¾Ð¼Ð¾Ð¶ÐµÑ Ð½Ð°Ð¼ обÑаÑÑÑÑ Ñ Ð²Ð¾ÑкеÑом.
function QueryableWorker(url, defaultListener, onError) {
var instance = this,
worker = new Worker(url),
listeners = {};
this.defaultListener = defaultListener || function () {};
if (onError) {
worker.onerror = onError;
}
this.postMessage = function (message) {
worker.postMessage(message);
};
this.terminate = function () {
worker.terminate();
};
}
ÐаÑем Ð¼Ñ Ð´Ð¾Ð±Ð°Ð²Ð»Ñем меÑÐ¾Ð´Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ/ÑÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±ÑабоÑÑиков.
this.addListeners = function (name, listener) {
listeners[name] = listener;
};
this.removeListeners = function (name) {
delete listeners[name];
};
ÐдеÑÑ Ð¼Ñ Ñоздадим Ñ worker-а два пÑоÑÑÑÑ ÑобÑÑÐ¸Ñ Ð´Ð»Ñ Ð¿ÑимеÑа: полÑÑение ÑазниÑÑ Ð´Ð²ÑÑ ÑиÑел и Ñоздание оповеÑÐµÐ½Ð¸Ñ ÑеÑез ÑÑи ÑекÑндÑ. Ðо ÑнаÑала нам нÑжно ÑеализоваÑÑ Ð¼ÐµÑод sendQuery, коÑоÑÑй пÑовеÑÐ¸Ñ ÐµÑÑÑ Ð»Ð¸ вообÑе Ñ worker-а обÑабоÑÑик, коÑоÑÑй Ð¼Ñ ÑобиÑаемÑÑ Ð²ÑзваÑÑ.
/*
ÐÑа ÑÑнкÑÐ¸Ñ Ð¿ÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð¿Ð¾ кÑайней меÑе один аÑгÑменÑ: Ð¸Ð¼Ñ Ð¼ÐµÑода, коÑоÑÑй Ð¼Ñ Ñ
оÑим вÑзваÑÑ.
Ðалее Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ пеÑедаÑÑ Ð¼ÐµÑÐ¾Ð´Ñ Ð½ÐµÐ¾Ð±Ñ
одимÑе ÐµÐ¼Ñ Ð°ÑгÑменÑÑ.
*/
this.sendQuery = function () {
if (arguments.length < 1) {
throw new TypeError(
"QueryableWorker.sendQuery takes at least one argument",
);
return;
}
worker.postMessage({
queryMethod: arguments[0],
queryArguments: Array.prototype.slice.call(arguments, 1),
});
};
ÐавеÑÑим QueryableWorker меÑодом onmessage
. ÐÑли worker Ð¸Ð¼ÐµÐµÑ ÑооÑвеÑÑÑвÑÑÑий меÑод, коÑоÑÑй Ð¼Ñ Ð·Ð°Ð¿ÑоÑили, он Ñакже должен веÑнÑÑÑ ÑооÑвеÑÑÑвÑÑÑий обÑабоÑÑик и аÑгÑменÑÑ, коÑоÑÑе нам нÑжнÑ. ÐÑÑанеÑÑÑ Ð»Ð¸ÑÑ Ð½Ð°Ð¹Ñи его в listeners
:
worker.onmessage = function (event) {
if (
event.data instanceof Object &&
event.data.hasOwnProperty("queryMethodListener") &&
event.data.hasOwnProperty("queryMethodArguments")
) {
listeners[event.data.queryMethodListener].apply(
instance,
event.data.queryMethodArguments,
);
} else {
this.defaultListener.call(instance, event.data);
}
};
ТепеÑÑ Ðº ÑÐ°Ð¼Ð¾Ð¼Ñ worker-Ñ. СнаÑала ÑледÑÐµÑ Ð¾Ð¿ÑеделиÑÑ ÑÑи два пÑоÑÑÑÑ Ð¼ÐµÑода:
var queryableFunctions = {
getDifference: function (a, b) {
reply("printStuff", a - b);
},
waitSomeTime: function () {
setTimeout(function () {
reply("doAlert", 3, "seconds");
}, 3000);
},
};
function reply() {
if (arguments.length < 1) {
throw new TypeError("reply - takes at least one argument");
return;
}
postMessage({
queryMethodListener: arguments[0],
queryMethodArguments: Array.prototype.slice.call(arguments, 1),
});
}
/* This method is called when main page calls QueryWorker's postMessage method directly*/
function defaultReply(message) {
// do something
}
Ð onmessage
:
onmessage = function (event) {
if (
event.data instanceof Object &&
event.data.hasOwnProperty("queryMethod") &&
event.data.hasOwnProperty("queryMethodArguments")
) {
queryableFunctions[event.data.queryMethod].apply(
self,
event.data.queryMethodArguments,
);
} else {
defaultReply(event.data);
}
};
ÐолнÑй код пÑимеÑа:
example.html (оÑÐ½Ð¾Ð²Ð½Ð°Ñ ÑÑÑаниÑа):
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>MDN Example - Queryable worker</title>
<script type="text/javascript">
/*
QueryableWorker instances methods:
* sendQuery(queryable function name, argument to pass 1, argument to pass 2, etc. etc): calls a Worker's queryable function
* postMessage(string or JSON Data): see Worker.prototype.postMessage()
* terminate(): terminates the Worker
* addListener(name, function): adds a listener
* removeListener(name): removes a listener
QueryableWorker instances properties:
* defaultListener: the default listener executed only when the Worker calls the postMessage() function directly
*/
function QueryableWorker(url, defaultListener, onError) {
var instance = this,
worker = new Worker(url),
listeners = {};
this.defaultListener = defaultListener || function () {};
if (onError) {
worker.onerror = onError;
}
this.postMessage = function (message) {
worker.postMessage(message);
};
this.terminate = function () {
worker.terminate();
};
this.addListener = function (name, listener) {
listeners[name] = listener;
};
this.removeListener = function (name) {
delete listeners[name];
};
/*
This functions takes at least one argument, the method name we want to query.
Then we can pass in the arguments that the method needs.
*/
this.sendQuery = function () {
if (arguments.length < 1) {
throw new TypeError(
"QueryableWorker.sendQuery takes at least one argument",
);
return;
}
worker.postMessage({
queryMethod: arguments[0],
queryMethodArguments: Array.prototype.slice.call(arguments, 1),
});
};
worker.onmessage = function (event) {
if (
event.data instanceof Object &&
event.data.hasOwnProperty("queryMethodListener") &&
event.data.hasOwnProperty("queryMethodArguments")
) {
listeners[event.data.queryMethodListener].apply(
instance,
event.data.queryMethodArguments,
);
} else {
this.defaultListener.call(instance, event.data);
}
};
}
// your custom "queryable" worker
var myTask = new QueryableWorker("my_task.js");
// your custom "listeners"
myTask.addListener("printStuff", function (result) {
document
.getElementById("firstLink")
.parentNode.appendChild(
document.createTextNode("The difference is " + result + "!"),
);
});
myTask.addListener("doAlert", function (time, unit) {
alert("Worker waited for " + time + " " + unit + " :-)");
});
</script>
</head>
<body>
<ul>
<li>
<a
id="firstLink"
href="javascript:myTask.sendQuery('getDifference', 5, 3);"
>What is the difference between 5 and 3?</a
>
</li>
<li>
<a href="javascript:myTask.sendQuery('waitSomeTime');"
>Wait 3 seconds</a
>
</li>
<li>
<a href="javascript:myTask.terminate();">terminate() the Worker</a>
</li>
</ul>
</body>
</html>
my_task.js (код worker-а):
var queryableFunctions = {
// пÑÐ¸Ð¼ÐµÑ #1: полÑÑиÑÑ ÑазниÑÑ Ð¼ÐµÐ¶Ð´Ñ Ð´Ð²ÑÐ¼Ñ ÑиÑлами
getDifference: function (nMinuend, nSubtrahend) {
reply("printStuff", nMinuend - nSubtrahend);
},
// пÑÐ¸Ð¼ÐµÑ #2: подождаÑÑ ÑÑи ÑекÑндÑ
waitSomeTime: function () {
setTimeout(function () {
reply("doAlert", 3, "seconds");
}, 3000);
},
};
// ÑиÑÑемнÑе ÑÑнкÑии
function defaultReply(message) {
// your default PUBLIC function executed only when main page calls the queryableWorker.postMessage() method directly
// do something
}
function reply() {
if (arguments.length < 1) {
throw new TypeError("reply - not enough arguments");
return;
}
postMessage({
queryMethodListener: arguments[0],
queryMethodArguments: Array.prototype.slice.call(arguments, 1),
});
}
onmessage = function (oEvent) {
if (
oEvent.data instanceof Object &&
oEvent.data.hasOwnProperty("queryMethod") &&
oEvent.data.hasOwnProperty("queryMethodArguments")
) {
queryableFunctions[oEvent.data.queryMethod].apply(
self,
oEvent.data.queryMethodArguments,
);
} else {
defaultReply(oEvent.data);
}
};
Ðожно пеÑеклÑÑаÑÑ ÑодеÑжимое каждой главной ÑÑÑаниÑÑ -> worker и worker -> ÑообÑение главной ÑÑÑаниÑÑ. Римена ÑвойÑÑв "queryMethod", "queryMethodListeners", "queryMethodArguments" могÑÑ Ð±ÑÑÑ Ð»ÑбÑми пока они ÑоглаÑÑÑÑÑÑ Ñ QueryableWorker
и worker
.
Google Chrome 17+ and Firefox 18+ имеÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Ð¿ÐµÑедаÑи опÑеделÑннÑÑ
Ñипов обÑекÑов (пеÑедаваемÑе обÑекÑÑ ÑеализÑÑÑие Transferable
инÑеÑÑейÑ) к или из worker-а Ñ Ð²ÑÑокой пÑоизводиÑелÑноÑÑÑÑ. ÐÑи обÑекÑÑ Ð¿ÐµÑедаÑÑÑÑ Ð¸Ð· одного конÑекÑÑа в дÑÑгой без опеÑаÑий копиÑованиÑ, ÑÑо пÑÐ¸Ð²Ð¾Ð´Ð¸Ñ Ðº знаÑиÑелÑÐ½Ð¾Ð¼Ñ Ð¿Ð¾Ð²ÑÑÐµÐ½Ð¸Ñ Ð¿ÑоизводиÑелÑноÑÑи пÑи оÑпÑавке болÑÑиÑ
набоÑов даннÑÑ
. ÐÑмайÑе об ÑÑом как о пеÑедаÑе по ÑÑÑлке в миÑе C/C++. Ðднако в оÑлиÑии Ð¾Ñ Ð¿ÐµÑедаÑи по ÑÑÑлке, "веÑÑиÑ" из вÑзÑваÑÑего конÑекÑÑа болÑÑе недоÑÑÑпна поÑле пеÑедаÑи. ÐладелÑÑем ÑÑановиÑÑÑ Ð½Ð¾Ð²Ñй конÑекÑÑ. ÐÐ»Ñ Ð¿ÑимеÑа, поÑле пеÑедаÑи ArrayBuffer
из главной ÑÑÑаниÑÑ Ðº worker-Ñ, иÑÑ
однÑй ArrayBuffer
оÑиÑаеÑÑÑ Ð¸ более недоÑÑÑпен Ð´Ð»Ñ Ð¸ÑполÑзованиÑ. Ðго ÑодеÑжание (в бÑквалÑном ÑмÑÑле) пеÑеноÑиÑÑÑ Ð² ÑабоÑий конÑекÑÑ.
// Create a 32MB "file" and fill it.
var uInt8Array = new Uint8Array(1024 * 1024 * 32); // 32MB
for (var i = 0; i < uInt8Array.length; ++i) {
uInt8Array[i] = i;
}
worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);
ÐÑимеÑание: ÐÐ»Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑной инÑоÑмаÑии о пеÑедаваемÑÑ Ð¾Ð±ÑекÑÐ°Ñ , пÑоизводиÑелÑноÑÑи и поддеÑжки Ð´Ð»Ñ ÑÑого меÑода, ÑиÑайÑе Transferable Objects: Lightning Fast! на HTML5 Rocks.
ÐÑÑÑоеннÑе worker-ÑÐе ÑÑÑеÑÑвÑÐµÑ ÑÑвеÑждÑнного ÑпоÑоба вÑÑÑоиÑÑ ÐºÐ¾Ð´ worker-а в ÑамкаÑ
веб-ÑÑÑаниÑÑ, как ÑÐ»ÐµÐ¼ÐµÐ½Ñ <script>
Ð´ÐµÐ»Ð°ÐµÑ Ð´Ð»Ñ Ð¾Ð±ÑÑнÑÑ
ÑкÑипÑов. Ðо ÑÐ»ÐµÐ¼ÐµÐ½Ñ <script>
, коÑоÑÑй не Ð¸Ð¼ÐµÐµÑ Ð°ÑÑибÑÑа src
и аÑÑибÑÑа type
, коÑоÑÐ¾Ð¼Ñ Ð½Ðµ назнаÑен вÑполнÑемÑй MIME type, можно ÑÑиÑаÑÑ Ð±Ð»Ð¾ÐºÐ¾Ð¼ даннÑÑ
Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ JavaScript. Ðлок даннÑÑ
"Data blocks" â ÑÑо более обÑее ÑвойÑÑво HTML5, Ð¼Ð¾Ð¶ÐµÑ ÑодеÑжаÑÑ Ð»ÑбÑе ÑекÑÑовÑе даннÑе. Так, worker Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð²ÑÑÑоен ÑледÑÑÑим обÑазом:
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>MDN Example - Embedded worker</title>
<script type="text/js-worker">
// ÐÑÐ¾Ñ script ÐÐ ÐУÐÐТ анализиÑоваÑÑÑÑ JS движками, поÑÐ¾Ð¼Ñ ÑÑо его MIME-Ñип text/js-worker.
var myVar = 'Hello World!';
// ÐÑÑалÑÐ½Ð°Ñ ÑаÑÑÑ ÐºÐ¾Ð´Ð° ваÑего воÑкеÑа идÑÑ ÑÑда.
</script>
<script type="text/javascript">
// ÐÑÐ¾Ñ script ÐУÐÐТ пÑоанализиÑован JS движкам, поÑÐ¾Ð¼Ñ ÑÑо его MIME-Ñип text/javascript.
function pageLog(sMsg) {
// Use a fragment: browser will only render/reflow once.
var oFragm = document.createDocumentFragment();
oFragm.appendChild(document.createTextNode(sMsg));
oFragm.appendChild(document.createElement("br"));
document.querySelector("#logDisplay").appendChild(oFragm);
}
</script>
<script type="text/js-worker">
// ÐÑÐ¾Ñ script ÐÐ ÐУÐÐТ анализиÑоваÑÑÑÑ JS движками, поÑÐ¾Ð¼Ñ ÑÑо его MIME-Ñип text/js-worker.
onmessage = function(oEvent) {
postMessage(myVar);
};
// ÐÑÑалÑÐ½Ð°Ñ ÑаÑÑÑ ÐºÐ¾Ð´Ð° ваÑего воÑкеÑа идÑÑ ÑÑда.
</script>
<script type="text/javascript">
// ÐÑÐ¾Ñ script ÐУÐÐТ пÑоанализиÑован JS движкам, поÑÐ¾Ð¼Ñ ÑÑо его MIME-Ñип text/javascript.
// РпÑоÑлом...:
// blob builder ÑÑÑеÑÑвовал
// ... но ÑепеÑÑ Ð¼Ñ Ð¸ÑполÑзÑем Blob...:
var blob = new Blob(
Array.prototype.map.call(
document.querySelectorAll("script[type='text\/js-worker']"),
function (oScript) {
return oScript.textContent;
},
),
{ type: "text/javascript" },
);
// Создание нового ÑвойÑÑва document.worker, ÑодеÑжаÑего вÑе наÑи "text/js-worker" ÑкÑипÑÑ.
document.worker = new Worker(window.URL.createObjectURL(blob));
document.worker.onmessage = function (oEvent) {
pageLog("Received: " + oEvent.data);
};
// ÐапÑÑк воÑкеÑа.
window.onload = function () {
document.worker.postMessage("");
};
</script>
</head>
<body>
<div id="logDisplay"></div>
</body>
</html>
ÐÑÑÑаиваемÑй worker ÑепеÑÑ Ð²Ð½ÐµÑÑн в новое custom ÑвойÑÑво document.worker
Также ÑÑÐ¾Ð¸Ñ Ð¾ÑмеÑиÑÑ, ÑÑо Ð²Ñ Ñакже можеÑе пÑеобÑазоваÑÑ ÑÑнкÑÐ¸Ñ Ð² BLOB-обÑекÑ, а заÑем ÑгенеÑиÑоваÑÑ URL обÑекÑа из ÑÑого BLOB-обÑекÑа. ÐапÑимеÑ:
function fn2workerURL(fn) {
var blob = new Blob(["(" + fn.toString() + ")()"], {
type: "application/javascript",
});
return URL.createObjectURL(blob);
}
ÐÑÑгие пÑимеÑÑ
Ð ÑÑой ÑекÑии пÑедÑÑавлено еÑÑ Ð½ÐµÑколÑко пÑимеÑов как иÑполÑзоваÑÑ worker-Ñ.
ÐÑполнение вÑÑиÑлений в ÑонеWorker-Ñ Ð² оÑновном Ð¿Ð¾Ð»ÐµÐ·Ð½Ñ Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ð¸ÑÑ Ð²Ð°ÑÐµÐ¼Ñ ÐºÐ¾Ð´Ñ Ð²ÑполнÑÑÑ ÑеÑÑÑÑоÑмкие вÑÑиÑлениÑ, не блокиÑÑÑ Ð¿Ð¾Ñок полÑзоваÑелÑÑкого инÑеÑÑейÑа. Ð ÑÑом пÑимеÑе, worker иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð²ÑÑиÑÐ»ÐµÐ½Ð¸Ñ ÑиÑла ФибонаÑÑи.
Ðод JavaScriptСледÑÑÑий код JavaScript Ñ ÑаниÑÑÑ Ð² Ñайле "fibonacci.js", на коÑоÑÑй ÑÑÑлаеÑÑÑ HTML в ÑледÑÑÑем Ñазделе.
var results = [];
function resultReceiver(event) {
results.push(parseInt(event.data));
if (results.length == 2) {
postMessage(results[0] + results[1]);
}
}
function errorReceiver(event) {
throw event.data;
}
onmessage = function (event) {
var n = parseInt(event.data);
if (n == 0 || n == 1) {
postMessage(n);
return;
}
for (var i = 1; i <= 2; i++) {
var worker = new Worker("fibonacci.js");
worker.onmessage = resultReceiver;
worker.onerror = errorReceiver;
worker.postMessage(n - i);
}
};
Worker ÑÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ ÑвойÑÑво onmessage
Ð´Ð»Ñ ÑÑнкÑии, коÑоÑÐ°Ñ Ð±ÑÐ´ÐµÑ Ð¿Ð¾Ð»ÑÑаÑÑ ÑообÑениÑ, оÑпÑавленнÑе пÑи вÑзове postMessage()
ÑабоÑего обÑекÑа (обÑаÑиÑе внимание, ÑÑо ÑÑо оÑлиÑаеÑÑÑ Ð¾Ñ Ð¾Ð¿ÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð³Ð»Ð¾Ð±Ð°Ð»Ñной пеÑеменной Ñ Ñаким именем или опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÑÑнкÑии Ñ Ñаким именем. var onmessage
и function onmessage
бÑÐ´ÐµÑ Ð¾Ð¿ÑеделÑÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑнÑе ÑвойÑÑва Ñ ÑÑими именами , но они не бÑдÑÑ ÑегиÑÑÑиÑоваÑÑ ÑÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ ÑообÑений, оÑпÑавленнÑÑ
веб-ÑÑÑаниÑей, коÑоÑÐ°Ñ Ñоздала worker). ÐÑо запÑÑÐºÐ°ÐµÑ ÑекÑÑÑиÑ, поÑÐ¾Ð¶Ð´Ð°Ñ Ð½Ð¾Ð²Ñе копии Ð´Ð»Ñ Ð¾Ð±ÑабоÑки каждой иÑеÑаÑии вÑÑиÑлениÑ.
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Test threads fibonacci</title>
</head>
<body>
<div id="result"></div>
<script language="javascript">
var worker = new Worker("fibonacci.js");
worker.onmessage = function (event) {
document.getElementById("result").textContent = event.data;
dump("Got: " + event.data + "\n");
};
worker.onerror = function (error) {
dump("Worker error: " + error.message + "\n");
throw error;
};
worker.postMessage("5");
</script>
</body>
</html>
Ðеб-ÑÑÑаниÑа ÑоздаÑÑ ÑÐ»ÐµÐ¼ÐµÐ½Ñ div
Ñ ID result
, коÑоÑÑй иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð¾ÑобÑÐ°Ð¶ÐµÐ½Ð¸Ñ ÑезÑлÑÑаÑа, а заÑем поÑÐ¾Ð¶Ð´Ð°ÐµÑ worker. ÐоÑле поÑÐ¾Ð¶Ð´ÐµÐ½Ð¸Ñ worker-а, обÑабоÑÑик onmessage
наÑÑÑоен Ð´Ð»Ñ Ð¾ÑобÑÐ°Ð¶ÐµÐ½Ð¸Ñ ÑезÑлÑÑаÑов пÑÑÑм ÑÑÑановки ÑодеÑжимого ÑлеменÑа div
, и обÑабоÑÑик onerror
наÑÑÑоен на вÑбÑÐ¾Ñ ÑообÑÐµÐ½Ð¸Ñ Ð¾Ð± оÑибке.
ÐаконеÑ, ÑообÑение оÑпÑавлÑеÑÑÑ worker-Ñ, ÑÑÐ¾Ð±Ñ Ð·Ð°Ð¿ÑÑÑиÑÑ ÐµÐ³Ð¾.
ÐопÑобÑйÑе ÑÑÐ¾Ñ Ð¿ÑимеÑ.
ÐÑполнение веб I/O в ÑонеÐÑ Ð¼Ð¾Ð¶ÐµÑе найÑи пÑÐ¸Ð¼ÐµÑ ÑÑого в ÑÑаÑÑе ÐÑполÑзование worker-ов в ÑаÑÑиÑениÑÑ .
Разделение Ð·Ð°Ð´Ð°Ñ Ð¼ÐµÐ¶Ð´Ñ Ð¼Ð½Ð¾Ð¶ÐµÑÑвеннÑми worker-амиÐоÑколÑÐºÑ Ð¼Ð½Ð¾Ð³Ð¾ÑдеÑнÑе компÑÑÑеÑÑ ÑÑановÑÑÑÑ Ð²Ñе более ÑаÑпÑоÑÑÑанÑннÑми, ÑаÑÑо бÑÐ²Ð°ÐµÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾ ÑазделиÑÑ Ð²ÑÑиÑлиÑелÑно ÑложнÑе задаÑи Ð¼ÐµÐ¶Ð´Ñ Ð½ÐµÑколÑкими worker-ами, коÑоÑÑе заÑем могÑÑ Ð²ÑполниÑÑ ÑÑи задаÑи на многопÑоÑеÑÑоÑнÑÑ ÑдÑÐ°Ñ .
ÐÑÑгие ÑÐ¸Ð¿Ñ worker-овРдополнение к вÑделеннÑм и ÑовмеÑÑно иÑполÑзÑемÑм web worker-ам доÑÑÑÐ¿Ð½Ñ Ð´ÑÑгие ÑÐ¸Ð¿Ñ worker-ов:
ChromeWorker
Ð´Ð»Ñ Ð±Ð¾Ð»ÐµÐµ подÑобной инÑоÑмаÑии.ÐнÑÑÑи web worker-а Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе иÑполÑзоваÑÑ Ð±Ð¾Ð»ÑÑинÑÑво ÑÑандаÑÑнÑÑ ÑÑнкÑий JavaScript, вклÑÑаÑ:
Navigator
XMLHttpRequest
Array
, Date
, Math
, и String
Window.requestAnimationFrame
, WindowTimers.setTimeout
, и WindowTimers.setInterval
Ðлавное, ÑÑо Ð²Ñ Ð½Ðµ можеÑе ÑделаÑÑ Ð² Worker ÑÑо напÑÑмÑÑ Ð¿Ð¾Ð²Ð»Ð¸ÑÑÑ Ð½Ð° ÑодиÑелÑÑкÑÑ ÑÑÑаниÑÑ. ÐÑо вклÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ Ð¼Ð°Ð½Ð¸Ð¿ÑлиÑование DOM и иÑполÑзование обÑекÑов ÑÑой ÑÑÑаниÑÑ. ÐÑ Ð´Ð¾Ð»Ð¶Ð½Ñ ÑделаÑÑ ÑÑо коÑвенно, оÑпÑавив ÑообÑение обÑаÑно оÑÐ½Ð¾Ð²Ð½Ð¾Ð¼Ñ ÑÑенаÑÐ¸Ñ ÑеÑез DedicatedWorkerGlobalScope.postMessage
, а заÑем вÑполнив Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¾ÑÑÑда.
ÐÑимеÑание: ÐÐ»Ñ Ð·Ð½Ð°ÐºÐ¾Ð¼ÑÑва Ñ Ð¿Ð¾Ð»Ð½Ñм ÑпиÑком ÑÑнкÑий, доÑÑÑпнÑÑ Ð´Ð»Ñ worker-ов, ÑмоÑÑиÑе ÑÑаÑÑÑ Ð¤ÑнкÑии и инÑеÑÑейÑÑ Ð´Ð¾ÑÑÑпнÑе worker-ам.
СпеÑиÑикаÑии СмоÑÑиÑе ÑакжеRetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4