When it comes to HTML5, people always talk about it. There are so many features and interesting APIs that are refreshing. However, many children's shoes still stay at the semantic stage and ignore the power of HTML5.
In this section we will discuss multi-threaded Web-Worker.
1. Make it clear that JavaScript is single-threadedA major feature of the JavaScript language is that it is single-threaded, which means that it can only do one thing at a time.
It sounds weird, why not design it with multi-threading to improve efficiency? We can assume a scenario:
Assume that JavaScript
has two threads at the same time. One thread adds content to a certain DOM
node, and the other thread deletes the node. In this case, which thread should the browser use?
As a browser scripting language, the main purpose of JavaScript
is to interact with users and manipulate DOM
.
This determines that it can only be single-threaded, otherwise it will cause very complex synchronization problems. In order to avoid complexity, JavaScript
has been single-threaded since its birth. This has become a core feature of the language and is expected to be difficult to change in the short term.
Single threading has always been a pain point. In order to take advantage of the computing power of multi-core CPU
, HTML5
proposes the Web Worker
standard, which allows JavaScript
scripts to create multiple threads. However, the child thread is completely controlled by the main thread and must not operate DOM
.
Therefore, this new standard does not change the single-threaded nature of JavaScript
.
Web Workers
is a JavaScript
multi-threading solution provided by modern browsers. We can find many usage scenarios:
1. We can use Web Worker
to do some computationally intensive operations;
2. Polling can be implemented and certain states can be changed;
3. Header message status update, such as notification of the number of messages in the page header;
4. High-frequency user interaction, spelling check, for example: assisting users to complete input error correction and correction functions based on user input habits, historical records, cache and other information
5. Encryption: Encryption can sometimes be very time-consuming, especially if you need to encrypt a lot of data frequently (for example, encrypting data before sending it to the server).
6. Prefetch data: In order to optimize your website or web application and improve data loading time, you can use Workers
to load some data in advance in case you need it.
Encryption is a great scenario for using Web Worker
because it doesn't require access to DOM
or other magic, it just purely uses algorithms to perform calculations. As the public pays increasing attention to sensitive personal data, information security and encryption have become top priorities. This can be reflected from the recent 12306 user data leakage incident.
Once the calculation is performed in the Worker, it is seamless to the user and does not affect the user experience.
3. Compatibility 4. Basic concepts1. First remember to judge whether it is supported
if (window.Worker) { ...}
2. Creating a new worker
is easy
const myWorker = new Worker('worker.js');
The postMessage() method and the onmessage event handler are the black magic of Workers.
3. postMessage
is used to send messages, and onmessage
is used to listen to messages.
const worker = new Worker('src/worker.js');worker.onmessage = e => { console.log(e.data);};worker.postMessage('How are you!');
When used in the main thread, onmessage
and postMessage()
must be hung on the worker
object, but this is not required when used in worker
. The reason is that, inside worker
, worker
is effectively the global scope.
4.Exception handling:
worker.onerror = function(error) { console.log(error.message); throw error;};
5. Terminate worker
worker.terminate();
The worker
thread is killed immediately, without any chance for it to complete its operations or clean up.
6. In the worker
thread, workers
can also call their own close
method to close:
close();5. Quick start
In order to quickly grasp, let's do a small example: the project structure is as follows
├── index.html└── src ├── main.js └── worker.js
Html
<html><head> <title>Web Work Demo</title> <meta charset=UTF-8 /></head><body> <div id=app> Hello Jartto! </div> <script src=src /main.js></script></body></html>
main.js
const worker = new Worker('src/worker.js');worker.onmessage = e => { const message = e.data; console.log(`[From Worker]: ${message}`); document.getElementById ('app').innerHTML = message;};worker.postMessage('Well written!');
Work.js
onmessage = e => { const message = e.data; console.log(`[From Main]: ${message}`); if(message.indexOf('Good') > -1) { postMessage('Thank you for your support '); }};
The code is very simple. The main thread sends: "It's so well written!"
The web worker received the message and found that the content contained the word "good" and sent it back to the main thread: "Thank you for your support."
6. Limitations 1. Within worker
, DOM
nodes cannot be directly manipulated, and the default methods and properties of the window
object cannot be used. However, we can use a large number of things under the window
object, including data storage mechanisms such as WebSockets
, IndexedDB
, and FireFox OS
specific Data Store API
.
Here is an example, we modify main.js
:
const worker = new Worker('src/worker.js');worker.onmessage = e => { const message = e.data; console.log(`[From Worker]: ${message}`); document.getElementById ('app').innerHTML = message;};+ worker.onerror = function(error) {+ console.log(error);+ worker.terminate();+ };worker.postMessage('Well written!');
Let’s modify work.js
again
+ alert('jartto');onmessage = e => { const message = e.data; console.log(`[From Main]: ${message}`); if(message.indexOf('good') > - 1) { postMessage('Thank you for your support'); }};
At this time, running will report:
This is because: the context in which worker.js
is executed is different from the context in which HTML
of the main page is executed. The top-level object is not Window
, the global context for woker.js
execution, but WorkerGlobalScope
. Let us explain in detail.
2. Data transfer between workers
and the main thread is carried out through such a message mechanism: both parties use the postMessage()
method to send their own messages, and use the onmessage
event handler to respond to the message (the message is included in the data
attribute of the Message
event).
In this process, data is not shared but copied.
3. Same origin restriction
The script file assigned to Worker
thread must have the same origin as the script file of the main thread.
4. File restrictions
The Worker
thread cannot read local files, that is, it cannot open the local file system (file://)
. The script it loads must come from the server.
5. Local files not allowed
Uncaught SecurityError: Failed to create a worker:
script at '(path)/worker.js'
cannot be accessed from origin 'null'.
Chrome doesn't let you load web workers when running scripts from a local file.
So how to solve it? We can start a local server. It is recommended to use http-server
, which is simple and easy to use.
6. Content Security Policy
worker
has its own execution context, distinct from the document
object that created it. So generally speaking, worker
is not restricted by the content security policy of document
(or parent worker
) that created it.
Let's take an example, assuming a document
has the following header declaration:
Content-Security-Policy: script-src 'self'
Part of the purpose of this declaration is to prohibit the script code contained within it from using the eval()
method. However, if the script code creates a worker
, code executing in the context of worker
can use eval()
.
In order to specify a CSP for a worker, the request to send the worker code must itself be appended with a CSP.
The one exception is that if the source of the worker
script is a globally unique identifier (for example, its URL
specifies a data schema or blob
), worker
will inherit document
or worker
CSP
that created it.
About, we can find the documentation on MDN
:
1. self
:
We can use the self
property of WorkerGlobalScope
to get a reference to the object itself.
2. location
:
The location
attribute returns WorkerLocation
object associated with the thread when it was created. It represents the absolute URL
of the script resource used to initialize the worker thread. This URL
resource location will not change even if the page is redirected multiple times.
3. close
:
Close the current thread, similar to terminate
.
4. caches
:
The current context has CacheStorage
to ensure offline availability and the response to the request can be customized.
5. console
:
Support console
syntax.
6. importScripts
We can load library functions in worker
through url
through importScripts()
method.
7. XMLHttpRequest
With it, Ajax
requests can be made.
8. You can use:
There are many API
that can be used, so I won’t give examples one by one here.
When worker
encounters a running error, its onerror
event handler will be called. It will receive an event named error
that extends the ErrorEvent
interface. The event does not bubble up and can be canceled.
To prevent the default action from being triggered, the worker can call the preventDefault() method of the error event.
We commonly use the following three key pieces of information for error events:
worker.onerror = function(error) { console.log(error.message); throw error;};
The above is the entire content of this article. I hope it will be helpful to everyone’s study. I also hope everyone will support VeVb Wulin Network.