javascript:Web Worker

Original sentence: Https://Wangdoc.Com/javascript/index.Html

Web Worker

Outline

JavaScript language uses single-threaded model, that is, all tasks can only be completed on a thread, you can only do one thing. The task ahead is not done, the latter task can only wait. With the increased computing power, and especially the emergence of multi-core CPU, single-threaded great deal of inconvenience, not full computing power.

Web Worker role, is to create a multi-threaded environment for JavaScript that allows the main thread creates Worker threads, the latter will assign some tasks to run. While the main thread running, Worker threads running in the background, the two non-interfering. Wait until Worker thread to complete computing tasks, and then return the results to the main thread. The advantage is that some high-latency or compute-intensive tasks can be handed over to Worker thread execution, the main thread (usually responsible for UI interactions) to maintain smooth, not blocked or slowed down.

Worker thread once the new success, it will always run, will not be active on the main thread (such as the user clicks the button to submit the form) interrupted. This facilitates communication at any time in response to the main thread. But it also caused Worker consuming resources, should not be overused, and once after use, they should be closed.

There are several Web Worker use and pay attention.

(1) homologous to limit

Worker threads allocated to run the script file, the script file must be homologous with the main thread.

(2) the DOM limit

Worker threads global object is located, and the main thread is not the same, DOM objects can not read the page where the main thread can not be used document, window, parentthese objects. However, Worker threads can use navigatorobjects and locationobjects.

(3) global objects limits

Worker global objects WorkerGlobalScope, unlike the global object pages Window, many interfaces get. For example, in theory Worker threads can not be used console.log, because the standard there is no mention of the existence Worker global object consoleinterface only defines the Navigatorinterface and the Locationinterface. However, the browser actually supports Worker threads console.log, insurance practice or not to use this method.

(4) communication links

Worker thread and the main thread is not in the same context, they can not communicate directly, it must be done through a message.

(5) script limit

Worker threads can not execute alert()methods and confirm()methods, it may be used an AJAX request XMLHttpRequest object.

(6) file limits

Worker thread was unable to read local files that can not turn on the machine file system ( file://), it loads the script, it must come from the network.

Basic Usage

The main thread

The main thread uses newthe command, call Worker()the constructor to create a new Worker thread.

var worker = new Worker('work.js');

Worker()Argument to the constructor is a script file, which is the task of Worker threads to be executed. Because Worker can not read local files, so the script must come from the network. If the download is not successful (for example, 404), Worker will silently fail.

Then, the main thread calls the worker.postMessage()method, a message to the Worker.

worker.postMessage('Hello World');
worker.postMessage({method: 'echo', args: ['Work']});

worker.postMessage()Parameter method, the main thread is passed Worker data. It may be various types of data including binary data.

Next, the main thread through worker.onmessagedesignated listener function, receiving a message sent back child thread.

worker.onmessage = function (event) {
  doSomething(event.data);
}

function doSomething() {
  // 执行任务
  worker.postMessage('Work done!');
}

In the above code, the event object dataproperty can obtain data sent by the Worker.

After Worker to complete the task, the main thread can turn it off.

worker.terminate();

Worker thread

Worker internal thread needs to have a monitor function, monitor messagethe event.

self.addEventListener('message', function (e) {
  self.postMessage('You said: ' + e.data);
}, false);

The above code, selfon behalf of the child thread itself, namely sub-thread global object. Thus, it is equivalent to the following two kinds of writing.

// 写法一
this.addEventListener('message', function (e) {
  this.postMessage('You said: ' + e.data);
}, false);

// 写法二
addEventListener('message', function (e) {
  postMessage('You said: ' + e.data);
}, false);

In addition to using self.addEventListener()the specified monitor function can also be used self.onmessageto specify. Parameter monitor function is an event object whose dataproperty contains the data sent by the main thread. self.postMessage()A method for sending a message to the main thread.

The data sent to the main thread, the Worker thread can call different methods, the following is an example.

self.addEventListener('message', function (e) {
  var data = e.data;
  switch (data.cmd) {
    case 'start':
      self.postMessage('WORKER STARTED: ' + data.msg);
      break;
    case 'stop':
      self.postMessage('WORKER STOPPED: ' + data.msg);
      self.close(); // Terminates the worker.
      break;
    default:
      self.postMessage('Unknown command: ' + data.msg);
  };
}, false);

In the above code, self.close()for closing the interior Worker itself.

Worker load scripts

Internal Worker If you want to load additional scripts, there is a special method importScripts().

importScripts('script1.js');

The method can load multiple scripts simultaneously.

importScripts('script1.js', 'script2.js');

Error Handling

The main thread can monitor whether Worker error occurred. If an error occurs, Worker will trigger the main thread of errorevents.

worker.onerror(function (event) {
  console.log([
    'ERROR: Line ', event.lineno, ' in ', event.filename, ': ', event.message
  ].join(''));
});

// 或者
worker.addEventListener('error', function (event) {
  // ...
});

Worker can also monitor internal errorevents.

Close Worker

After use, in order to conserve system resources, it must be closed Worker.

// 主线程
worker.terminate();

// Worker 线程
self.close();

data communication

As mentioned above, communications between the main thread and the Worker, can be text, or may be an object. It should be noted that this is a copy of the communication relationship, that is, by value rather than pass-by, Worker modify the content of the communication, will not affect the main thread. In fact, the operating mechanism inside browser, first communication content serializer, the string is then sent to the Worker serialized, which then restore it.

Worker thread and also between the main exchange binary data, such as File, Blob, ArrayBuffer other types, may be transmitted between threads. Below is an example.

// 主线程
var uInt8Array = new Uint8Array(new ArrayBuffer(10));
for (var i = 0; i < uInt8Array.length; ++i) {
  uInt8Array[i] = i * 2; // [0, 2, 4, 6, 8,...]
}
worker.postMessage(uInt8Array);

// Worker 线程
self.onmessage = function (e) {
  var uInt8Array = e.data;
  postMessage('Inside worker.js: uInt8Array.toString() = ' + uInt8Array.toString());
  postMessage('Inside worker.js: uInt8Array.byteLength = ' + uInt8Array.byteLength);
};

However, send a copy of the binary data can cause performance problems. For example, the main thread to send a 500MB file to the Worker, the browser will generate a copy of the original file by default. To solve this problem, JavaScript allows the main thread to transfer binary data directly to the sub-thread, but once transferred, the main thread will no longer be able to use these binary data, which is to prevent the emergence of multiple threads to modify troublesome situation data. This data transfer method, called the Transferable Objects . This allows the main thread can quickly put data to the Worker, for image processing, audio processing, 3D and other operations is very convenient, no performance overhead.

If you want to direct transfer of control data, you must use the following wording.

// Transferable Objects 格式
worker.postMessage(arrayBuffer, [arrayBuffer]);

// 例子
var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);

Web Worker same page

Typically, Worker loaded script is a separate JavaScript file, but can also be loaded with the main thread in the same web page code.

<!DOCTYPE html>
  <body>
    <script id="worker" type="app/worker">
      addEventListener('message', function () {
        postMessage('some message');
      }, false);
    </script>
  </body>
</html>

The above is a piece of embedded script pages, attention must specify the <script>label typeattribute value is a browser does not know, the case is app/worker.

Then, read the script embedded in the page of this section, to deal with the Worker.

var blob = new Blob([document.querySelector('#worker').textContent]);
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);

worker.onmessage = function (e) {
  // e.data === 'some message'
};

The above code, the first script code embedded in the page, conversion to a binary object and then generates a URL for the binary object, let Worker load the URL. This done, the main thread and the Worker's code on the same page above.

Examples: Worker threads to complete poll

Sometimes, the browser needs to poll the server status, so the first time that a state change. This work can be placed Worker inside.

function createWorker(f) {
  var blob = new Blob(['(' + f.toString() + ')()']);
  var url = window.URL.createObjectURL(blob);
  var worker = new Worker(url);
  return worker;
}

var pollingWorker = createWorker(function (e) {
  var cache;

  function compare(new, old) { ... };

  setInterval(function () {
    fetch('/my-api-endpoint').then(function (res) {
      var data = res.json();

      if (!compare(data, cache)) {
        cache = data;
        self.postMessage(data);
      }
    })
  }, 1000)
});

pollingWorker.onmessage = function () {
  // render data
}

pollingWorker.postMessage('init');

The above code, Worker polling data once per second, then do compare with the cache. If not, it means that the server with the new changes, so must notify the main thread.

Examples: Worker New Worker

Internal Worker Worker threads can then create a new thread (currently only supported by Firefox browser). The following example is a computationally intensive task, 10 assigned to Worker.

The main thread code is as follows.

var worker = new Worker('worker.js');
worker.onmessage = function (event) {
  document.getElementById('result').textContent = event.data;
};

Worker thread code is as follows.

// worker.js

// settings
var num_workers = 10;
var items_per_worker = 1000000;

// start the workers
var result = 0;
var pending_workers = num_workers;
for (var i = 0; i < num_workers; i += 1) {
  var worker = new Worker('core.js');
  worker.postMessage(i * items_per_worker);
  worker.postMessage((i + 1) * items_per_worker);
  worker.onmessage = storeResult;
}

// handle the results
function storeResult(event) {
  result += event.data;
  pending_workers -= 1;
  if (pending_workers <= 0)
    postMessage(result); // finished!
}

In the above code, the internal thread built Worker Worker threads 10, and sequentially transmits this message to the Worker 10, to inform the start and end calculation. Computing tasks script code is as follows.

// core.js
var start;
onmessage = getStart;
function getStart(event) {
  start = event.data;
  onmessage = getEnd;
}

var end;
function getEnd(event) {
  end = event.data;
  onmessage = null;
  work();
}

function work() {
  var result = 0;
  for (var i = start; i < end; i += 1) {
    // perform some complex calculation here
    result += 1;
  }
  postMessage(result);
  close();
}

API

The main thread

Browser native in the Worker()constructor for the main thread to create for Worker threads.

var myWorker = new Worker(jsUrl, options);

Worker()Constructor can accept two parameters. The first parameter is the URL of the script (must comply with the same-origin policy), this parameter is required, and can only be loaded JS script, otherwise it will error. The second parameter is the configuration object optional. Its role is to specify the name of Worker, used to distinguish between multiple Worker threads.

// 主线程
var myWorker = new Worker('worker.js', { name : 'myWorker' });

// Worker 线程
self.name // myWorker

Worker()Constructor returns a Worker thread object, the main thread is used for the operation Worker. Worker thread object properties and methods as follows.

  • Worker.onerror: Specifies the listener function error events.
  • Worker.onmessage: Specifies the message event listener functions, data sent from the Event.dataproperty.
  • Worker.onmessageerror: Specifies the listener function messageerror events. When sending data can not be serialized into a String, it will trigger this event.
  • Worker.postMessage (): send a message to the Worker threads.
  • Worker.terminate (): immediate termination of Worker threads.

Worker thread

Web Worker has its own global object, not the main thread window, but tailored specifically for Worker global object. Thus defined windownot use all the above objects and methods.

Worker thread has some of its own global properties and methods.

  • self.name: Worker's name. This read-only attribute, specified by the constructor.
  • self.onmessage: Specifies the messagelistener function event.
  • self.onmessageerror: Specifies the listener function messageerror events. When sending data can not be serialized into a String, it will trigger this event.
  • self.close (): Close Worker threads.
  • self.postMessage (): sending a message to generate the Worker thread.
  • self.importScripts (): Load JS script.

(Finish)

Guess you like

Origin www.cnblogs.com/wbyixx/p/12499586.html