Dedicated Web Worker (Dedicated Web Worker) provides a simple way to allow Web content to run the script in the background. Once the worker is created, it can pass the message to the event monitoring function specified by its creator, so that all the tasks generated by the worker will receive these messages. The worker thread can perform tasks without interference UI. In addition, it can also use XMLHTTPREQUEST (although the two attribute values of Responsexml and Channel are always NULL) to perform I/O operations. This article provides examples and details to make up the previous documents. The function provided to worker lists the functions supported by Worker.
The Worker interface will generate a real operating system -level thread. If you are not careful, then the concurrency will have an interesting impact on your code. However, for Web Worker, communication points with other threads will be carefully controlled, which means that it is difficult for you to cause complication. You have no way to access non -threaded security components or DOMs. In addition, you need to interact with thread -specific data through serialized objects. So if you don't spend some effort, you can't make mistakes. Generate worker
It is very simple to create a new worker. All you have to do is call the worker () constructor, and specify a URI that needs to run a script that is running in the worker thread. If you want to receive the notification of Worker, you can set the Worker's OnMessage property to a specific event processing function.
var myWorker = New Worker (my_task.js); MyWorker.onMessage = Function (OEvent) {console.log (Called back by the worker!/n);};Or, you can also use addeventlistener ():
var myWorker = New Worker (my_task.js); MyWorker.adDeventListener (Message, Function (OEVENT) {console.log (Called back by the worker!/n);}, false); Ker.postmessage (); // Start The worker.The first line in the example creates a new worker thread. The third act sets the monitoring function of the MESSAGE event. When worker calls its own postmessage () function, this event processing function is called. Finally, the Worker thread was launched in the seventh line. Note: The parameter URI that transmits the worker constructor must follow the homologous strategy. At present, different browser manufacturers are still different about which URIs should follow the homologous strategies; GECKO 10.0 (Firefox 10.0 / Thunderbird 10.0 / Seamonkey 2.7) and subsequent versions are allowed to be passed into Data URI, while the Internet Explorer 10 does not think Blob URI. It is an effective script for Worker.
Pass dataThe data transmitted between the homepage and the worker is copied, not shared. The object passed to the worker needs to be serialized, and then the next end needs to be serialized. The page does not share the same example as Worker. The end result is that a copy of the data is generated at the end of each communication. Most browsers use structured copy to achieve this feature.
Before going down, for the purpose of teaching, let us create a function called EmulatingMessage (). It will simulate the "copy instead of sharing from the worker to the main page (vice versa). "Behavior:
Function EmulatingMessage (VVAL) {Return Eval ; // Objectalert (Typeof EmulatingMessage (Example1); // Number // test #2Var Example2 = True; Alert (Typeof Example2); // Booleanalert (Typeof EmulatingMessage (Example2)); // Boolean // Test #3V #3V ar example3 = New String (Hello World) ; Alert (Typeof Example3); // Objectalert (Typeof EmulatingMessage (Example3)); // String // Test #4Var Example4 = {name: John Smith, Age: 43}; Alert (Typeof Example4); // Objectalert (Typeof EmulatingMessage (Example4); // Object // Test #5Function Animal (style, name) {This.Type = style; this.age = name;} Var Example5 = New Animal (Cat, 3); Alert (example5.conStructor ); // Animalalert (emulatingMessage (example5) .conStructor); // ObjectThe value that is not shared is called message. Let's talk about worker, you can use postmessage () to pass the message to the main thread or send it back from the main thread. The Data attribute of the MESSAGE event contains data from Worker.
Example.html: (Homepage): var myWorker = New Worker (my_task.js); MyWorker.onMessage = Function (OEvent) {console.log (worker said: + EEVENT.DATA);}; myWorker.postmessage (ali) ; my_task.js (worker): Postmessage ;Note: Generally speaking, background threads -including worker -unable to operate DOM. If the background thread needs to modify the DOM, then it should send the message to its founder so that the creator to complete these operations.
As you can see, the message transmitted between worker and homepage is always "JSON message", even if it is a original type of value. Therefore, you can transmit json data and/or any data type that can serialize:
PostMessage ({cmd: init, timestamp: date.now ()});Examples to pass data
Example#1: Create a common "asynchronous Eval ()"
The following example introduces how to use EVAL () in Worker to execute any type of JavaScript code in any type of asynchronous in order::
// syntax: asynceVal (code [, listner]) var asYNCEVAL = (FUNCTION () {Var Alistener = [], OPARSER = New worker (data: text/javascript; charset = us-aSCIII , onMessage%20%3d%20Function %20%28oevent%29%20%7b%0a%09postmessage%28%7b%09%09%22id%22%20oevent.data%2c%09%22evaluate%22%3A 3A 3A 3A 3A 3A 3A 3A 3A 3A %20Eval%28oevent.data.Code%29%0a%09%7d%29%3b%0A%7d); oprser.onMessage = FUNCTION (OEVENT) {if (AListens [OEVENT.DATA.D]) {alistener [EEVENT .data.id] (EEVENT.DATA.Evaluated);} Delete Alisteners [EEVENT.DATA.ID];}; Return Function (Scode, FLIISTENER) {Alisteners.push (Flistener || Null); OPAR ser.postmessage ({ID : Alisteners.Length -1, code: scode});};});Example use:
// Asynchronous Alert Message ... AsynceVal (3 + 2, Function (SMESSAGE) {Alert (3 + 2 = + Smessage); // Asynchronous Print ... AsynceVal (// Hello World !!!/,,, Function (SHTML) {document.body.appendchild (document.createTextNode (shtml);}); // Asynchronous void ... asynceVal (()/n/TVar {/n/TVar = new xmlhttprequest ();/n/ Toreq.open (/get/, /http://www.mozilla.org//, false);/n/Toreq.Send (NULL);/n/treturn oreq.Responsetext;/n});));));));));));));)));));));)));)));)));)));)));Example#2: Transfer the advanced method of JSON and create an exchange system
If you need to transmit very complicated data, and you need to call multiple methods on the homepage and worker at the same time, then you can consider creating a system similar to the following.
Example.html (the main page): <! Doctype html> <html> <gead> <meta charset = UTF -8 /> <Title> MDN Example -Queryable Worker < /Title> <Script Type = Text /JavaScript> 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.protodype. PostMessage () * Terminate (): Terminates the worker * addlistener (name, function): Adds a Listener * Removelistener (name): Removes a Listener Queeryker Instances Properties: * DEFAULTLISTLISTENER: The Default Listener Executem only when the worker calls the postmessage () function directly */ function queryableworker (Surl, FDEFLISTENER, Fonerror ) {Var OINSTANCE = This, OWORCER = New Worker (Surl), Olistener = {}; this.DefaultListener = FDEFLISTENER || Function () {}; Event) {ifvent.data Instanceof Object && OEvent.data.hasownproperty (VO42T30) && & ievent.data.hasownProperty (RNB93QH) {Olisteners [EEVENT.DATA.VO42T30] .apply (OIEVENT.DATA.RNB99 3qh);} else {this.defaultListener.call (oinstance, OEVENT.DATA);}}; if (fonerror) {owster.onerror = fonerror;} this.SendQuery = Function (/* queryable function name, argument to pass 1, argument to pass 2, 2, 2, ETC. ETC */) {if (Arguments.Length <1) {Throw New Typerror (QueryableWorker.SendQuery -NOT Enough Arguments); Return;} Oworker.postmessage ({BK4E1H0: Arguments [0] , KTP3FM1: Array.prototype.slice.Call (Arguments, 1) });}; this.postmessage = Function (vmsg) {// i just Think there is no need to use call () How about just out of (VMSG); // The s ame sitation with terminate // Well, Just a little faster, no search up the prototy worker.prototype.postMessage.call (OWORKER, VMSG); This.terminate = Function () {worker.Prot OTYPE.Terminate.Call (OWORKER);}; this .Addlistener = Function (SNAME, FLISTENER) {Olistener [SNAME] = Flistener;}; This.removelistener = Function (SNAME) {delete Olistener [SNAME];}; / / Your Custom Queeryable Worker Var Omytask = New Queryableworker ( My_task.js / *, yourDefaultMessagelistener Wee [Optional], yourerrrorListenerhere [optional] * /); // Your Custom Listener Omytask.addlistener (PRINTSOMETH Ing, Function (NRESULT) {Document.GetelementByid (Firstlink) .parentNode.appendchild (Document.CreateTextNode ( The display is + nresult +!);});}); Omytask.addlistener (Alertsomething, Function (NDeltat, SUNIT) {Alert (worker waitd for + + + :-))) ;}); </script> < /Head> <body> <ul> <li> <A ID = firstlink href = javascript: Omytask.sendquery ('Getdifferente', 5, 3);> What is the difference between 5 and 3? </a> </</ li> <li> <A href = javascript: omytask.sendquery ('waitsomething'); Inate ( ) The worker </a> </li> </ul> </body> </html> my_task.js (the worker): // Your Custom Private FunctionSFunction MyprivateFunc1 () {// Do Something} Funct} Funct Ion myprivatefunc2 () {// Do Something} // ETC. ETC.// Your Custom Public Functions (IE Queryable From the Main Page) Var QueryableFunctions = {// Example #1: Get The Difference Bet Ween Two Nightrs: Getdifference: Function (NMINUND, NSUBTRAHEND ) {Reply (Printsomething, NMINUEND -NSUBTRAHEND);}, // Example #2: Wait Three Seconds Waitsomething: Function () {Settimeout (Function () {ALERERERERER tsomething, 3, sex);}, 3000);}} ; // System FunctionSFUNCTION DefaultQuery (VMSG) {// Your Default Public Function Execuad Main Page Calls the Queryableer.postmessage (). Method Directly // Do Something} Function Reply (/* Listener name, Argument to pass 1, argument to Pass 2, ETC. ETC */) {if (Arguments.Length <1) {Throw New Typerror (Reply -NOT ENUGH ARGUMENTS); Return;} Postmessage ({VO42T30: Arguments [0 ], RNB93QH: Array.prototype.slice .call (arguments, 1)});} OnMessage = Function (OEVENT) {if (EEVENT.DATA Instanceof Object &&SOWNPROPERTY) &&DAEENPROPRTY (BK4E1H0) .hasownproperty (ktp3fm1)) {queryableFunction [EEVENT.DATA .bk4e1h0] .apply (self, oEvent.data.ktp3fm1);} else {defaultQuery (EEVENT.DATA);}};This is a very suitable method to switch the news between homepage -worker-or the opposite-the opposite-the opposite.
Transfer data by transferring ownership (transferable object)
Google Chrome 17 and Firefox 18 include another method with a higher performance to pass the specific type of object (transferable object) to a worker/back from the worker. The transfer object is transferred from one context to another context without any copy operation. This means that it will get great performance improvement when passing big data. If you come from the C/C ++ world, then imagine it as a transmission according to reference. However, unlike the conveying according to the reference, once the object is transferred, the version that the original context will no longer exist. The ownership of the object is transferred to the new context. For example, when you transfer an ArrayBuffer object from the main application to the worker, the original ArrayBuffer is cleared and cannot be used. The content it contains (complete) will be passed to the worker context.
// Create A 32MB FILE and FILL It.var UINT8ARRAY = New UINT8ARAY (1024*1024*32); // 32MBFOR (VAR I = 0; I <uint8array .Length; ++ I) {UINT8ARAY [i] = i ;; } worker.postmessage (UINT8ARRAY.BUFFER, [UINT8ARAY.BUFFER]); Generate subworkerIf necessary, Worker can generate more workers. This is called SubWorker, who must host in the same source as the parent page. In the same way, SubWorker analyzes the URI's address rather than his own page instead of its own page. This makes Worker easily monitor their dependence. Chrome does not support SubWorker.
Embedded workerThere is currently no "official" method that can embed the worker code into a web page like <script> elements. But if a <Script> element does not have SRC characteristics, and its type characteristics are not specified as a running MIME-TYPE, then it will be considered a data block element and can be used by JavaScript. "Data block" is a very common feature in HTML5, which can carry almost any type of text type data. Therefore, you can embed a worker in the following way:
<! Doctype html> <html> <wead> <meta charset = UTF-8/> <Title> MDN Example-Embedded Worker </Title> <script Type = Text/JS-Worker> // This script will not be js. The engine analysis, because its MIME-TYPE is Text/JS-Worker. Var myvar = Hello World!; // The remaining worker code is written here. </script> <script type = text/javascript> // The script will be analyzed by the JS engine because its Mime-Type is Text/JavaScript. Function Pagelog (SMSG) {// Use Fragment: In this way, the browser will only rendering/rearring. var ofragm = document.createdocumenTFRAGMENT (); ofragm.appendchild (Document.createTextNode (SMSG)); R)); Document.queryselector (#Logdisplay) .appndchild (ofragm);} </Script > <script type = Text/JS-Workr> // This script will not be parsed by the JS engine because its MIME-TYPE is Text/JS-Worker. onMessage = Function (OEVENT) {PostMessage (myvar);}; // The remaining worker code is written here. </script> <script type = text/javascript> // The script will be analyzed by the JS engine because its Mime-Type is Text/JavaScript. // In the past ...: // We use blob builder // ... but now we use blob ...: var blob = new blob (array.prototype.map.call (documens.quelySelectorary (script [type = = /text // js- workr/], function (oscript) {return oscript.textContent;}), {type: text/javascript}); // Create a new Document.Worker property, which contains all Text/J. s- Worker script. document.Worker = New Worker (Window.url.CreateObjectUrl (Blob)); Document.Worker.onMessage = FUNCTION (OEVENT) {Pagelog (Received: + OEVENT.DATA); }; // Start worker. Window.onload = Function () {document.Worker.postmessage ();}; </script> </head> <body> <div ID = logdisplay> </body> </html>Now, the embedded worker has been set into a customized Document.Worker property.
Timeout and intervalWorker can use timeout and interval like the main thread. This will be very useful, for example, if you want the worker thread to periodically without uninterrupted running code.
Termination workerIf you want to terminate a worker immediately, you can call the Terminate () method of Worker::
myWorker.terMinate ();
The worker thread will be killed immediately and will not leave any opportunity to let it complete its own operation or cleanup work.
Workers can also call your own nsiWorkerScope.close () method to close yourself:
self.close ();Process errors
When the worker is runtime errors, its onerror event processing function is called. It receives an event that implements the ERROREVENT interface name ERROR. The incident will not be bubbling and can be canceled; in order to prevent the default action, Worker can call the PreventdeFault () method of the wrong event. The error event has the following three fields that are interested in:
MessageReadable error messages.
filenameError script file name.
linenoThe line number of the script file when an error occurs.
Visit Navigator objectWorkers can access Navigator objects in its scope. It contains the following string that can recognize the browser, as doing it in ordinary scripts:
The worker thread can access a global function, ImportScripts (), which allows Worker to introduce the script or library into its own scope. You can introduce the URI without passing the parameters, or to the URI of multiple scripts; the following examples are legal:
ImportScripts (); /* Nothing to introduce* /ImportScripts ('Foo.js'); /* only introduce foo.js* /ImportScripts ('foo.js', 'bar.js'); /* introduces two. script*/The browser loads and runs the script. The global objects in each script can be used by Worker. If the script cannot be loaded, the Network_ERROR exception will be thrown, and the next code will not be executed. The code that previously executed (including the code executed using Window.Settimeout ()) can still be used. The function declaration after ImportScripts () can still be used because they are always running before other code. Note: The download order of the script is not fixed, but the order will be passed into the importScripts () () when executed. This is completed simultaneously; until all scripts are downloaded and running, ImportScripts () will return.
exampleThis section provides several examples of how to use Dom Worker.
Execute operations in the background
One of the advantages of Worker is that it can execute the dense operation of the processor without blocking the UI thread. In the following example, Worker is used to calculate Fibona.
Javascript code
The following JavaScript code is stored in the "fibonacci.js" file, which is associated with the html file in the next section.
Var Results = []; Function ResultReceiver (Event) {Results.push (PARSEINT (EVENT.DATA)); if (results.Length == 2) {PostMessage (Results [0] + Resu LTS [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; -I);}};Worker sets the attribute onMessage to a function. When the worker object calls Postmessage (), the function will receive the information sent. (Note that this use is not the same as defining a global variable with the same name, or a function of the same name. Var OnMessage and Function onMessage will define the same global attributes as the name, but they will not register The function of the message sent by the webpage.) This will enable recursion and generate your new copy to process each cycle of calculation.
HTML code
<! Doctype html> <html> <gead> <meta charset = UTF-8/> <TEST Threads Fibonacci </Title> </Head> <body> <DIV ID = Result> <script Languag E = javascript> var worker = new worker (fibonacci.js); worker.onMessage = Function (Event) {document.getElementByid (Result) .textContent = Event.data; D ump (GOT: + Event.data + /N);} ; worker.onerror = function (error) {dump (worker error: + error.message +/n); throw error;}; worker.postmessage (5); </script> </body> </html>The webpage creates a div element, the ID is result, using it to display the calculation result, and then generate a worker. After generating a worker, the onMessage processing function is configured to display the calculation results by setting the content of the DIV element, and then the Onerror processing function is set to the storage error information. Finally, send a message to Worker to start it.