SharedWorker

Интерфейс SharedWorker (разделяемый воркер) является особым видом воркеров к которому можно получить доступ из нескольких контекстов браузера, например, из нескольких окон, iframe, или других воркеров. Этот интерфейс реализован иначе, чем dedicated воркеры и имеют иной глобальный контекст, SharedWorkerGlobalScope.

Примечание: Если SharedWorker может быть доступен из нескольких контекстов браузера, все они должны разделять одинаковое расположение (идентичные протокол, хост и порт).

Примечание: В Firefox, разделяемые воркеры не могут взаимодействовать между private (например, просматриваемыми в приватном режиме) и non-private документами (см. Firefox bug 1177621.)

Свойства

Наследует свойства родителя, EventTarget, и реализует свойства AbstractWorker.

AbstractWorker.onerror

EventListener который вызывается всегда, когда ErrorEvent типа error всплывает через воркер.

SharedWorker.port Только для чтения

Возвращает объект MessagePort, используемый для коммуникации и контроля разделяемого воркера.

Constructors

SharedWorker()

Создаёт разделяемый веб воркер, который выполняет скрипт по указанному URL.

Методы

Наследует методы родительского класса, EventTarget, и реализует свойства AbstractWorker.

Пример

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

Следующий пример кода демонстрирует создание объекта SharedWorker с использованием конструктора SharedWorker(). Оба скрипта содержат:

js
var myWorker = new SharedWorker("worker.js");

далее скрипты получают доступ к воркеру через объект MessagePort, находящийся в свойстве SharedWorker.port. Если устанавливается обработчик события onmessage, port самостоятельно начинает работу, вызывая собственный метод start(), если же принимать события с помощью обработчика события "message" через addEventListener, необходимо вызвать метод start() самостоятельно:

js
myWorker.port.start();

После того, как порт запущен, оба скрипта отправляют сообщения воркеру и принимают их от него, используя port.postMessage() и port.onmessage, соответственно:

js
first.onchange = function () {
  myWorker.port.postMessage([first.value, second.value]);
  console.log("Message posted to worker");
};

second.onchange = function () {
  myWorker.port.postMessage([first.value, second.value]);
  console.log("Message posted to worker");
};

myWorker.port.onmessage = function (e) {
  result1.textContent = e.data;
  console.log("Message received from worker");
};

Внутри воркера используется хэндлер SharedWorkerGlobalScope.onconnect для соединения к тому же порту, как обсуждалось ранее. Порты, связанные с данным воркером доступны в свойстве ports события connect. Далее вызывается метод MessagePort start() для запуска порта, и устанавливается хэндлер onmessage для обработки сообщений, присылаемых от обоих потоков.

js
onconnect = function (e) {
  var port = e.ports[0];
  // or port = e.source

  port.addEventListener("message", function (e) {
    var workerResult = "Result: " + e.data[0] * e.data[1];
    port.postMessage(workerResult);
  });

  port.start(); // необходимо при добавлении обработчиков с помощью addEventListener. При использовании сеттера port.onmessage, данный метод вызывается автоматически, неявно
};

Пример с несколькими страницами

test.js

js
let connected = false;
self.addEventListener(
  "connect",
  (e) => {
    e.source.addEventListener(
      "message",
      (ev) => {
        if (ev.data === "start") {
          if (connected === false) {
            e.source.postMessage("worker init");
            connected = true;
          } else {
            e.source.postMessage("worker already inited");
          }
        }
      },
      false,
    );
    e.source.start();
  },
  false,
);

На странице 1 получаем сообщение 'worker init' в консоли.

index1.html

html
<script>
  let worker = new SharedWorker("test.js");
  worker.port.addEventListener(
    "message",
    (e) => {
      console.log(e.data);
    },
    false,
  );
  worker.port.start();
  worker.port.postMessage("start");
</script>

На странице 2 в консоль выводится 'worker already inited', так как страница 1 уже запустила наш воркер;

index2.html

html
<script>
  let worker = new SharedWorker("test.js");
  worker.port.addEventListener(
    "message",
    (e) => {
      console.log(e.data);
    },
    false,
  );
  worker.port.start();
  worker.port.postMessage("start");
</script>

Спецификации

Specification
HTML
# shared-workers-and-the-sharedworker-interface

Совместимость с браузерами

Report problems with this compatibility data on GitHub
desktopmobile
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
SharedWorker
SharedWorker() constructor
Support for ECMAScript modules
Strict MIME type checks for shared worker scripts
options.name parameter
options.sameSiteCookies parameter
options.type parameter
error event
port

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
Partial support
Partial support
No support
No support
See implementation notes.
Has more compatibility info.

Смотрите также