[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/ru/docs/Web/API/Web_Workers_API/Using_web_workers [Back]  [Original]

Web Workers - API | MDN

This page was translated from English by the community. Learn more and join the MDN Web Docs community.

View in English Always switch to English

Web Workers

Web Worker- . Worker' . , /, XMLHttpRequest ( responseXML channel null). Worker JavaScript - , ( ). Web Workers.

In this article

Web Workers API

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.

Workers

, Worker , . JavaScript, Worker ( ): , Worker, , .

, worker- . .

Worker

, worker- (main.js):

js
if (window.Worker) {

  ...

}

worker

worker- . Worker(), URI worker- (main.js):

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

worker

worker- postMessage() onmessage. worker, (main.js):

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):

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-:

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

textContent , .

: , onmessage() postmessage() Worker , worker-. , worker-, worker .

worker-

worker- terminate:

js
myWorker.terminate();

worker- .

worker-, onerror. error, ErrorEvent.

. , worker preventDefault() .

, :

message

.

filename

, .

lineno

, .

subworkers

Worker- worker-. sub-worker' (same-origin), . , URI subworker- worker', . worker- , .

Worker , importScripts(), . URI , ; :

js
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- (Shared workers)

worker , worker-. JavaScript, worker- ( worker): worker-, , : . worker .

worker-. , HTML JavaScript-, worker-.

: worker , ( , ).

: Firefox worker (Firefox bug 1177621).

worker-

worker- worker-, (. index.html index2.html) worker, :

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

, worker- port , worker- ( worker- ).

, onmessage, , start() , . start() , addEventListener().

: start() , worker-, .

js
myWorker.port.start(); //   
js
port.start(); //   worker-,   port    

/ worker-

worker-, , postMessage() port ( , multiply.js square.js):

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

worker-. (worker.js):

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):

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- .

js
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: ( ):

js
var myWorker = new Worker("my_task.js");

myWorker.onmessage = function (oEvent) {
  console.log("Worker said : " + oEvent.data);
};

myWorker.postMessage("ali");

my_task.js (worker):

js
postMessage("I'm working before postMessage('ali').");

onmessage = function (oEvent) {
  postMessage("Hi " + oEvent.data);
};

JSON , JSON , , .

#1: JSON

, worker-, .

QueryableWorker, url worker-, (defaultListener) . .

js
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();
  };
}

/ .

js
this.addListeners = function (name, listener) {
  listeners[name] = listener;
};

this.removeListeners = function (name) {
  delete listeners[name];
};

worker- : . sendQuery, worker- , .

js
/*
         :  ,    .
         .
 */
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:

js
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-. :

js
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:

js
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 ( ):

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-):

js
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 . ( ) .

js
// 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]);

worker-

worker- -, <script> . <script>, src type, MIME type, JavaScript. "Data blocks" HTML5, . , worker :

html
<!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-. :

js
function fn2workerURL(fn) {
  var blob = new Blob(["(" + fn.toString() + ")()"], {
    type: "application/javascript",
  });
  return URL.createObjectURL(blob);
}

worker-.

Worker- , , . , worker .

JavaScript

JavaScript "fibonacci.js", HTML .

js
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). , .

HTML

html
<!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-:

worker-

web worker- JavaScript, :

, Worker . DOM . , DedicatedWorkerGlobalScope.postMessage, .

: , worker-, worker-.

Specification
HTML
# workers


Web Proxy Viewer  |  New URL  |  Original Page