There is no doubt that JavaScript does not have multi-threading. It can only do one thing at a time. After doing one thing, do the next thing. If your jsIf it takes a long time to do one thing, the browser will freeze for a while and not respond to the user's operations. What can we do? Thank God, HTML5 provides us with a mechanism to implement multi-threading. You must have used such a good thing long ago, but it doesn't matter, let's review together!
1. Method introduction
(1)Constructor new Worker(arg): Parameters Indicates the js file where the code to be executed by your thread is located, such as 'myworker.js'. The constructor of course returns an instance of the Worker class
(2) worker.postMessage(message): This method indicates that from The main thread sends a message to the sub-thread or the sub-thread sends a message to the main thread. The message is usually a string , or a js object can be converted into a character Send it in series
(3) There is also a message event on the worker. When someone sends a message to this worker instance, the event is triggered. We can get the data from his event object. AttributesGet the posted value
You can see that the API of the Woker class is quite simple, with only two most commonly used methods and one event. Below we Let’s see through practical examples.
//main.html <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>main</title></head><body> <p id="out"></p> <input type="text" name="" id="txt"> <button id="btn">发送</button> <script type="text/javascript"> var out = document.getElementById("out"); var btn = document.getElementById("btn"); var txt = document.getElementById("txt"); var worker = new Worker("thread1.js"); btn.addEventListener("click",function(){ var postData = txt.value; worker.postMessage(postData); },false); worker.addEventListener('message',function(e){ out.innerText = e.data; },false); </script></body></html>
//thread1.js onmessage = function(event){ var res = event.data+"帅气!"; postMessage(res); }
When I enter "Big~Bear" in the text box and click the send button, the following effect will appear
Simple analysis , I created a Worker instance worker by thead1.js in the main thread. When the button is clicked, its postMessage method will be called to send the content in the text box to thread1.js. How does our thread1.js do it? That's it, it listens to the message event, and the main thread triggers the event when it sends a message, and executes the callback function. The callback function gets the value sent from the event object, and then adds "handsome!" to this value. , and then send it back. The main thread also listens to the worker's message event, so it will be triggered when a message passes, and the message content will be displayed in p, so you can see the above effect.
Perhaps you will use this for what purpose? There is really no use here. Here we can always complete the operation of adding "handsome!" in the main thread, because its complexity is O(1) (haha, I am learning algorithms recently!), but if it is not such a simple operation Woolen cloth? The advantage of this method is that no matter how complicated the work your sub-thread does, it will not stop the main thread. The main thread will continue to do whatever it is doing. Once the sub-thread has processed the data, it can just take it over. .
Teacher Lu will be able to create a new sub-thread by calling new Worker() in the sub-thread. I found that this is not possible and an undefined error will be reported, which means that the Worker construct cannot be called in the sub-thread. Function, I thought I was wrong at first, but later I checked the official documentation and found that there was no relevant description.
Let’s look at an example of calling multiple sub-threads in the main thread:
//main.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>main</title> </head> <body> <div id="out"></div> <input type="text" name="" id="txt"> <button id="btn">发送</button> <script type="text/javascript"> var out = document.getElementById("out"); var btn = document.getElementById("btn"); var txt = document.getElementById("txt"); var worker1 = new Worker("thread1.js"); var worker2 = new Worker("thread2.js"); btn.addEventListener("click",function(){ var postData = txt.value; worker1.postMessage(postData); },false); worker1.addEventListener('message',function(e){ worker2.postMessage(e.data); },false); worker2.addEventListener('message',function(e){ out.innerText = e.data; },false); </script> </body> </html>
//thread1.js onmessage = function(event){ var res = event.data+"帅气!"; postMessage(res); }
//thread2.js onmessage = function(event){ var res = event.data+"没骗你哟!"; postMessage(res); close(); }
The main thread needs two threads to complete a task. It creates two threads worker1 and 2, and first goes to worker1 Request, after getting the returned data, request worker2 again, and at the same time hand the data processed by worker1 to worder2 for processing, and then get the final result and display it on the page.
In the child thread, you can introduce other js files and then call them, such as the example below.
//main.html <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>main</title></head><body> <p id="out"></p> <input type="text" name="" id="txt"> <button id="btn">发送</button> <script type="text/javascript"> var out = document.getElementById("out"); var btn = document.getElementById("btn"); var txt = document.getElementById("txt"); var worker1 = new Worker("thread1.js"); btn.addEventListener("click",function(){ var postData = txt.value; worker1.postMessage(postData); },false); worker1.addEventListener('message',function(e){ out.innerText = e.data; },false); </script></body></html>
//thread1.js importScripts('tools.js') onmessage = function(event){ var res = handler(event.data); postMessage(res); }
//tools.js function handler(data){ return data+"加油加油!" }
You can see that our thread1.js does not have a file called tools.js, but it imports a js file through importScripts(), and then you can call the exposed methods inside.
The essence of SharedWorker is share. Different threads can share one thread, and their data is also shared.
Let’s discuss it directly with examples.
Usage method one:
//main.html <!DOCTYPE HTML><head> <title>Shared workers: demo 1</title></head><body> <p id="log"></p><script> var worker = new SharedWorker('shared.js'); var log = document.getElementById('log'); worker.port.onmessage = function(e) { // note: not worker.onmessage! log.textContent += '\n' + e.data; }</script></body></html>
//shared.js onconnect = function(e) { var port = e.ports[0]; port.postMessage('Hello World!'); }
This is an example taken from w3c. Let’s look at the second method first and then analyze it
<!DOCTYPE HTML> <html> <head> <title>Shared workers: demo 2</title> </head> <body> <p id="log"></p> <script> var worker = new SharedWorker('shared.js'); var log = document.getElementById('log'); worker.port.addEventListener('message', function(e) { log.textContent += '\n' + e.data; }, false); worker.port.start(); // note: need this when using addEventListener worker.port.postMessage('ping');</script> </body></html>
//shared onconnect = function(e) { var port = e.ports[0]; port.postMessage('Hello World!'); port.onmessage = function(e) { port.postMessage('pong'); // not e.ports[0].postMessage! // e.target.postMessage('pong'); would work also } }
第一种方法中是使用事件句柄的方式将听message事件,不需要调用worker.port.start(),第二种方法是通过addEventListener()方法监听message事件,需要worker.port.start()方法激活端口。他们不同于worker,当有人和他通信时触发connect事件,然后他的message事件是绑定在messagePort对象上的,不想worker那样,你可以回头看看worker是怎么做的。
那么sharedWorker是怎么共享数据的呢?请看下面的例子。
//main1 和main2都是这样 <!DOCTYPE HTML> <html> <head> <title>Shared workers: demo 2</title> </head> <body> <p id="log"></p> <input type="text" name="" id="txt"> <button id="get">get</button> <button id="set">set</button> <script> var worker = new SharedWorker('shared.js'); var get = document.getElementById('get'); var set = document.getElementById('set'); var txt = document.getElementById('txt'); var log = document.getElementById('log'); worker.port.addEventListener('message', function(e) { log.innerText = e.data; }, false); worker.port.start(); // note: need this when using addEventListener set.addEventListener('click',function(e){ worker.port.postMessage(txt.value); },false); get.addEventListener('click',function(e){ worker.port.postMessage('get'); },false);</script></body></html>
//shared var data; onconnect = function(e) { var port = e.ports[0]; port.onmessage = function(e) { if(e.data=='get'){ port.postMessage(data); }else{ data=e.data; } } }
这里分析一波,我们在main1.html的文本框输入数据,点击set,然后在main2.html中点击get法现能够获取到我们在main1.html中设置的数据,这说明我们的sharedWorker事实上是单例的,就像java中的static类一样,不管new多少个,实际上只有一个,这样我们的不同线程就可以共享到sharedWorker中的数据了。这里把图给上,记得有篇文章没给图,然后有人给我建议了,问能不能给图。
最后来小结一下,worker和sharedWorker没有什么悬糊的,就是把台前的工作搬到幕后去做,不打断台前的工作。正所谓台上十分钟,台下十年功,如果你把台下的十年供放到台上做,观众的唾沫星子早就把你淹死了,所以说那些费事费力的工作还是放到台下去,台上只用展示你最好的一面的好了,十分钟足以!
The above is the detailed content of Detailed code explanation of HTML5 new feature multi-threading (Worker SharedWorker). For more information, please follow other related articles on the PHP Chinese website!