Introduction and use of web worker

Introduction

What is a web worker? As you can see from the name, web worker is the worker used in web applications. This worker is a thread that runs in the background independent of the main web thread.

The advantage of web workers is that they can delegate work to other independent threads, so that they don't block the main thread.

Basic concepts and usage of Web Workers

Web workers are created by using Worker().

Worker can specify the script to be executed in the background, and usually creator after the script is executed.

The worker has a constructor as follows:

Worker("path/to/worker/script") 

We can create a worker by passing in the path of the script to be executed.

New Workers can also be created in Workers, provided that these workers are of the same origin.

Let's look at the definition of worker:

interface Worker extends EventTarget, AbstractWorker {
    
    
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;

    postMessage(message: any, transfer: Transferable[]): void;
    postMessage(message: any, options?: PostMessageOptions): void;

    terminate(): void;
    addEventListener<K extends keyof WorkerEventMap>(type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
    addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
    removeEventListener<K extends keyof WorkerEventMap>(type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
    removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}

declare var Worker: {
    
    
    prototype: Worker;
    new(stringUrl: string | URL, options?: WorkerOptions): Worker;
};

You can see that Worker's constructor can pass in two parameters. The first parameter can be a string or a URL, which indicates the path of the script to be executed.

The second parameter is the WorkerOptions option, which indicates the type, name, and permission-related options of the worker.

interface WorkerOptions {
    
    
    credentials?: RequestCredentials;
    name?: string;
    type?: WorkerType;
}

In addition, the worker can monitor two events, onmessage and onmessageerror.

Two methods are provided: postMessage and terminate.

Both worker and main thread can send messages to each other through postMessage, and can also use onmessage to receive messages sent by each other.

You can also add and remove EventListener.

Let's look at an example of using worker:

const first = document.querySelector('#number1');
const second = document.querySelector('#number2');

const result = document.querySelector('.result');

if (window.Worker) {
    
    
	const myWorker = new Worker("worker.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');
	}

	myWorker.onmessage = function(e) {
    
    
		result.textContent = e.data;
		console.log('Message received from worker');
	}
} else {
    
    
	console.log('Your browser doesn\'t support web workers.')
}

The above example creates a worker and posts a message to the worker.

Let's take a look at the content of worker.js:

onmessage = function(e) {
    
    
  console.log('Worker: Message received from main script');
  const result = e.data[0] * e.data[1];
  if (isNaN(result)) {
    
    
    postMessage('Please write two numbers');
  } else {
    
    
    const workerResult = 'Result: ' + result;
    console.log('Worker: Posting message back to main script');
    postMessage(workerResult);
  }
}

We post messages to the worker in the main thread, listen for messages through onmessage in the worker, and post messages in the worker, and we can listen to the messages sent by the worker through onmessage in the main thread.

In this way, a perfect interaction is achieved.

Let's take a look at the compatibility of workers:

As you can see, basically all browsers support workers, but some browsers only support some methods.

If we want to terminate a worker immediately, we can use terminate:

myWorker.terminate();

To handle worker exceptions, you can use onerror to handle exceptions.

If the script of the worker is more complicated and other script files are needed, we can use importScripts to import other scripts:

importScripts();                         /* imports nothing */
importScripts('foo.js');                 /* imports just "foo.js" */
importScripts('foo.js', 'bar.js');       /* imports two scripts */
importScripts('//example.com/hello.js'); /* You can import scripts from other origins */

Classification of Web Workers

Web Workers can be divided into DedicatedWorker and SharedWorker according to different working environments.

DedicatedWorker's Worker can only be accessed from the script that created the Woker, while SharedWorker can be accessed by multiple scripts.

In the above example, the worker we created is DedicatedWorker.

How to create sharedWorker?

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

SharedWorker has a separate SharedWorker class, and unlike dedicated worker, SharedWorker interacts through port objects.

Let's look at an example of a shared worker:

var first = document.querySelector('#number1');
var second = document.querySelector('#number2');

var result1 = document.querySelector('.result1');

if (!!window.SharedWorker) {
    
    
  var myWorker = new SharedWorker("worker.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');
    console.log(e.lastEventId);
  }
}

All postMessage and onmessage are based on myWorker.port.

Look at the worker code again:

onconnect = function(e) {
    
    
  var port = e.ports[0];

  port.onmessage = function(e) {
    
    
    var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
    port.postMessage(workerResult);
  }

}

Workers also communicate through ports.

Here we use onconnect to monitor the onmessage event or start event of the parent thread, both of which can start a SharedWorker.

Take a look at the browser compatibility of sharedWorker:

It can be seen that the compatibility is much lower than that of the worker, and only some browsers support this advanced feature.

Data transmission between worker and main thread

We know that the interaction between worker and main thread is through postMessage and onMessage. This involves the issue of data transmission.

In fact, data is transferred between the worker and the main thread in a copy mode and in a serialized form.

Author: flydean program those things

Link to this article: http://www.flydean.com/webworker-kickoff/

Source of this article: flydean's blog

Welcome to pay attention to my official account: the most popular interpretation of "programs", the most profound dry goods, the most concise tutorials, and many tips you don't know are waiting for you to discover!

Guess you like

Origin blog.csdn.net/superfjj/article/details/109351367