Compare Revisions

Using web workers

Revision 320893:

Revision 320893 by Yukoba on

Revision 321285:

Revision 321285 by ahcxlh on

Title:
Using web workers
Using web workers
Slug:
DOM/Using_web_workers
DOM/Using_web_workers
Tags:
"Workers","Firefox","Gecko 1.9.1","HTML5","JavaScript","NeedsTechnicalReview"
"Workers","Firefox","Gecko 1.9.1","HTML5","JavaScript","NeedsTechnicalReview"
Content:

Revision 320893
Revision 321285
t8      Dedicated Web Workers provide a simple means for web content8      data = require("self").data;<br>
>t to run scripts in background threads.&nbsp; Once created, a wor 
>ker can send messages to the spawning task by posting messages to 
> an event handler specified by the creator. 
9    </p>9      <br>
10    <p>10      var myPanel = require("panel").Panel({<br>
11      The worker thread can perform tasks without interfering wit11      width:350,<br>
>h the user interface.&nbsp; In addition, they can perform I/O usi 
>ng <code><a class="internal" href="/en/nsIXMLHttpRequest" title=" 
>En/XMLHttpRequest">XMLHttpRequest</a></code> (although the <code> 
>responseXML</code> &nbsp;and <code>channel</code> attributes are  
>always null). 
12    </p>12      height:140,<br>
13    <p>13      contentURL: "<a href="http://w.qq.com/" target="_blank">htt
 >p://w.qq.com/</a>"<br>
14      See {{ domxref("Worker") }} for reference documentation on 14      });<br>
>workers; this article complements that one by offering examples a 
>nd added details. For a list of functions available to workers, s 
>ee <a href="/en/DOM/Worker/Functions_available_to_workers" title= 
>"En/DOM/Worker/Functions available to workers">Functions availabl 
>e to workers</a> . 
15    </p>15      <br>
16    <h2 id="About_thread_safety">16      require("widget").Widget({<br>
17      About thread safety17      id:"qq_client",<br>
18    </h2>18      label:"mini qq's web",<br>
19    <p>19      contentURL:data.url("qq.png"),<br>
20      The <code>Worker</code> interface spawns real OS-level thre20      panel:myPanel<br>
>ads, and concurrency can cause interesting effects in your code i 
>f you aren't careful. However, in the case of web workers, the ca 
>refully controlled communication points with other threads means  
>that it's actually very hard to cause concurrency problems. &nbsp 
>;There's no access to non-thread safe components or the DOM and y 
>ou have to pass specific data in and out of a thread through seri 
>alized objects. &nbsp;So you have to work really hard to cause pr 
>oblems in your code. 
21    </p>
22    <h2 id="Spawning_a_worker">
23      Spawning a worker
24    </h2>
25    <p>
26      Creating a new worker is simple.&nbsp; All you need to do i
>s call the <code>Worker()</code> &nbsp;constructor, specifying th 
>e URI&nbsp;of a script to execute in the worker thread, and, if y 
>ou wish to be able to receive notifications from the worker, set  
>the worker's <code>onmessage</code> property to an appropriate ev 
>ent handler function. 
27    </p>
28    <div style="overflow:hidden">
29      <pre class="brush: js">
30var worker = new Worker('my_task.js');
31worker.onmessage = function(event) {
32 console.log("Called back by the worker!\n");
33};
34</pre>
35    </div>
36    <p>
37      Alternatively, you could use <code>addEventListener()</code
>> : 
38    </p>
39    <div style="overflow:hidden">
40      <pre class="brush: js">
41var worker = new Worker('my_task.js');
42worker.addEventListener('message', function(event) {
43 console.log("Called back by the worker!\n");
44}, false);
45 
46worker.postMessage(""); // start the worker.
47</pre>
48    </div>
49    <p>
50      Line 1 in this example creates a new worker thread.&nbsp; L
>ine 2 sets up a listener to handle <code>message</code> events fr 
>om the worker. This event handler will be called when the worker  
>calls its own <code>postMessage()</code> &nbsp;function. Finally, 
> Line 6 starts the worker thread. 
51    </p>
52    <div class="note">
53      <strong>Note</strong> : The URI passed as parameter of the 
><code>Worker</code> constructor must obey the <a href="/en/Same_o 
>rigin_policy_for_JavaScript" title="Same origin policy for JavaSc 
>ript">same-origin policy</a> . There is currently disagreement am 
>ong browsers vendors on whether data URIs are of the same-origin  
>or not; Gecko 10.0 {{ geckoRelease("10.0") }} and later do allow  
>data URIs as a valid script for workers. Other browsers may disag 
>ree. 
54    </div>
55    <h3 id="Passing_data">
56      Passing data
57    </h3>
58    <p>
59      Messages can be sent to and from the main thread by using <
>code>postMessage()</code> . The <code>message</code> event's <cod 
>e>data</code> attribute contains data passed back from the work. 
60    </p>
61    <p>
62      Main app :
63    </p>
64    <pre class="brush: js">
65var worker = new Worker('my_task.js');
66worker.onmessage = function(event) {
67  console.log("Worker said : " + event.data);
68};
69worker.postMessage('ali');
70</pre>
71    <p>
72      my_task.js :
73    </p>
74    <pre class="brush: js">
75self.postMessage("I'm working befor postMessage('ali').");
76self.onmessage = function(event) {
77  self.postMessage('Hi '+event.data);
78};
79</pre>
80    <div class="note">
81      <strong>Note:</strong> As usual, background threads—includi
>ng workers—cannot manipulate the DOM.&nbsp; If actions taken by t 
>he background thread need to result in changes to the DOM, they s 
>hould post messages back to their creators to do that work. 
82    </div>
83    <p>
84      Messages passed between the main page and workers are copie
>d, not shared. Objects are serialized as they're handed to the wo 
>rker, and subsequently, de-serialized on the other end. The page  
>and worker do not share the same instance, so the end result is t 
>hat a duplicate is created on each end. Most browsers implement t 
>his feature as <a href="/en/DOM/The_structured_clone_algorithm" t 
>itle="The structured clone algorithm">structured cloning</a> . 
85    </p>
86    <h4 id="Passing_JSON_data">
87      Passing JSON data
88    </h4>
89    <p>
90      It possible to pass JSON data (or any data type that can be
> serialized): 
91    </p>
92    <pre class="brush: js">
93postMessage({'cmd': 'init', 'timestamp': Date.now()});
94</pre>
95    <div class="note">
96      <strong>Note:</strong> Objects passed in and out of workers
> must not contain functions or cyclical references, since JSON&nb 
>sp;doesn't support these. 
97    </div>
98    <h4 id="Advanced_passing_JSON_Data_and_creating_a_switching_s
>ystem"> 
99      Advanced passing JSON Data and creating a switching system
100    </h4>
101    <p>
102      If you have to pass some complex data and have to call many
> different functions both in the main page and in the Worker, you 
> can create a system like the following. 
103    </p>
104    <p>
105      <strong>example.html</strong> (the main page):
106    </p>
107    <pre class="brush: html">
108&lt;!DOCTYPE html&gt;
109&lt;html&gt;
110&lt;head&gt;
111&lt;meta charset="UTF-8"  /&gt;
112&lt;title&gt;MDN Example - Queryable worker&lt;/title&gt;
113&lt;script type="text/javascript"&gt;
114  /*
115    QueryableWorker instances methods:
116     * sendQuery(queryable function name, argument to pass 1, arg
>ument to pass 2, etc. etc): calls a Worker's queryable function 
117     * postMessage(string or JSON Data): see Worker.prototype.pos
>tMessage() 
118     * terminate(): terminates the Worker
119     * addListener(name, function): adds a listener
120     * removeListener(name): removes a listener
121    QueryableWorker instances properties:
122     * defaultListener: the default listener executed only when t
>he Worker calls the postMessage() function directly 
123  */
124  function QueryableWorker (sURL, fDefListener, fOnError) {
125    var oInstance = this, oWorker = new Worker(sURL), oListeners 
>= {}; 
126    this.defaultListener = fDefListener || function () {};
127    oWorker.onmessage = function (oEvent) {
128      if (oEvent.data instanceof Object &amp;&amp; oEvent.data.ha
>sOwnProperty("vo42t30") &amp;&amp; oEvent.data.hasOwnProperty("rn 
>b93qh")) { 
129        oListeners[oEvent.data.vo42t30].apply(oInstance, oEvent.d
>ata.rnb93qh); 
130      } else {
131        this.defaultListener.call(oInstance, oEvent.data);
132      }21      });
133    };
134    if (fOnError) { oWorker.onerror = fOnError; }
135    this.sendQuery = function (/* queryable function name, argume
>nt to pass 1, argument to pass 2, etc. etc */) { 
136      if (arguments.length &lt; 1) { throw new TypeError("Queryab
>leWorker.sendQuery - not enough arguments"); return; } 
137      oWorker.postMessage({ "bk4e1h0": arguments[0], "ktp3fm1": A
>rray.prototype.slice.call(arguments, 1) }); 
138    };
139    this.postMessage = function (vMsg) {
140      Worker.prototype.postMessage.call(oWorker, vMsg);
141    };
142    this.terminate = function () {
143      Worker.prototype.terminate.call(oWorker);
144    };
145    this.addListener = function (sName, fListener) {
146      oListeners[sName] = fListener;
147    };
148    this.removeListener = function (sName) {
149      delete oListeners[sName];
150    };
151  };
152 
153  // your custom "queryable" worker
154  var oMyTask = new QueryableWorker("myTask.js" /* , yourDefaultM
>essageListenerHere (optional), yourErrorListenerHere (optional) * 
>/); 
155 
156  // your custom "listeners"
157 
158  oMyTask.addListener("printSomething", function (nResult) {
159    document.getElementById("firstLink").parentNode.appendChild(d
>ocument.createTextNode(" The difference is " + nResult + "!")); 
160  });
161 
162  oMyTask.addListener("alertSomething", function (nDeltaT, sUnit)
> { 
163    alert("Worker waited for " + nDeltaT + " " + sUnit + " :-)");
164  });
165&lt;/script&gt;
166&lt;/head&gt;
167&lt;body&gt;
168  &lt;ul&gt;
169    &lt;li&gt;&lt;a id="firstLink" href="javascript:oMyTask.sendQ
>uery('getDifference', 5, 3);"&gt;What is the difference between 5 
> and 3?&lt;/a&gt;&lt;/li&gt; 
170    &lt;li&gt;&lt;a href="javascript:oMyTask.sendQuery('waitSomet
>hing');"&gt;Wait 3 seconds&lt;/a&gt;&lt;/li&gt; 
171    &lt;li&gt;&lt;a href="javascript:oMyTask.terminate();"&gt;ter
>minate() the Worker&lt;/a&gt;&lt;/li&gt; 
172  &lt;/ul&gt;
173&lt;/body&gt;
174&lt;/html&gt;
175</pre>
176    <div class="note">
177      <strong>Note:</strong> Objects passed in and out of workers
> must not contain functions or cyclical references, since JSON&nb 
>sp;doesn't support these. 
178    </div>
179    <p>
180      <strong>myTask.js</strong> (the Worker):
181    </p>
182    <pre class="brush: js">
183// your custom PRIVATE functions
184 
185function myPrivateFunc1 () {
186  // do something
187}
188 
189function myPrivateFunc2 () {
190  // do something
191}
192 
193// etc. etc.
194 
195// your custom PUBLIC functions (i.e. queryable from the main pag
>e) 
196 
197var queryableFunctions = {
198  // example #1: get the difference between two numbers:
199  getDifference: function (nMinuend, nSubtrahend) {
200      reply("printSomething", nMinuend - nSubtrahend);
201  },
202  // example #2: wait three seconds
203  waitSomething: function () {
204      setTimeout(function() { reply("alertSomething", 3, "seconds
>"); }, 3000); 
205  }
206};
207 
208// system functions
209 
210function defaultQuery (vMsg) {
211  // your default PUBLIC function executed only when main page ca
>lls the queryableWorker.postMessage() method directly 
212  // do something
213}
214 
215function reply (/* listener name, argument to pass 1, argument to
> pass 2, etc. etc */) { 
216  if (arguments.length &lt; 1) { throw new TypeError("reply - not
> enough arguments"); return; } 
217  postMessage({ "vo42t30": arguments[0], "rnb93qh": Array.prototy
>pe.slice.call(arguments, 1) }); 
218}
219 
220self.onmessage = function (oEvent) {
221  if (oEvent.data instanceof Object &amp;&amp; oEvent.data.hasOwn
>Property("bk4e1h0") &amp;&amp; oEvent.data.hasOwnProperty("ktp3fm 
>1")) { 
222    queryableFunctions[oEvent.data.bk4e1h0].apply(self, oEvent.da
>ta.ktp3fm1); 
223  } else {
224    defaultQuery(oEvent.data);
225  }
226};
227</pre>
228    <div class="note">
229      <strong>Note:</strong> Objects passed in and out of workers
> must not contain functions or cyclical references, since JSON&nb 
>sp;doesn't support these. 
230    </div>
231    <p>
232      It is a possible method to switch the content of each mainp
>age-worker – and vice versa – message. 
233    </p>
234    <h4 id="Passing_data_by_transferring_.C2.A0ownership_(transfe
>rable_objects)"> 
235      Passing data by transferring &nbsp;ownership (transferable 
>objects) 
236    </h4>
237    <p>
238      Google Chrome 17 contains an additional way to pass data to
>/from a worker&nbsp;using&nbsp; <a class="external" href="http:// 
>dev.w3.org/html5/spec/common-dom-interfaces.html#transferable-obj 
>ects">Transferable Objects</a> &nbsp;with high performance.&nbsp; 
>With transferable objects, data is transferred from one context t 
>o another with a zero-copy operation. This means a vast performan 
>ce improvement when sending large data. Think of it as pass-by-re 
>ference if you're from the C/C++ world. However, unlike pass-by-r 
>eference, the 'version' from the calling context is no longer ava 
>ilable once transferred. Its ownership is transferred to the new  
>context. For example, when transferring an <font face="'Courier N 
>ew', 'Andale Mono', monospace"><span style="line-height: normal;" 
>>&nbsp; <a href="/en/JavaScript_typed_arrays/ArrayBuffer" title=" 
>ArrayBuffer">ArrayBuffer</a></span></font> &nbsp;from your main a 
>pp to Worker, the original&nbsp; <code>ArrayBuffer</code> &nbsp;i 
>s cleared and no longer usable. Its contents are (quite literally 
>) transferred to the Worker context. 
239    </p>
240    <p>
241      Chrome includes an additional prefixed version of <a href="
>/en/DOM/window.postMessage" title="window.postMessage">postMessag 
>e API</a> &nbsp;that supports transferable objects.&nbsp;The firs 
>t argument to the method is an&nbsp; <code>ArrayBuffer,&nbsp;</co 
>de> followed by an array of the items to transfer.&nbsp; 
242    </p>
243    <pre class="brush: js">
244// Create a 32MB "file" and fill it.
245var uInt8View = new Uint8Array(1024*1024*32); // 32MB
246for (var i = 0; i &lt; uInt8View.length; ++i) {
247  uInt8View[i] = i;
248}
249 
250worker.webkitPostMessage(uInt8Array.buffer, [uInt8Array.buffer]);
251</pre>
252    <p>
253      For more information on transferable objects,&nbsp; <a clas
>s="external" href="http://updates.html5rocks.com/2011/12/Transfer 
>able-Objects-Lightning-Fast" title="http://updates.html5rocks.com 
>/2011/12/Transferable-Objects-Lightning-Fast">see HTML5Rocks</a>  
>. 
254    </p>
255    <h2 id="Spawning_subworkers">
256      Spawning subworkers
257    </h2>
258    <p>
259      Workers may spawn more workers if they wish.&nbsp; So-calle
>d subworkers must be hosted within the same origin as the parent  
>page.&nbsp; Also, the URIs for subworkers are resolved relative t 
>o the parent worker's location rather than that of the owning pag 
>e.&nbsp; This makes it easier for workers to keep track of where  
>their dependencies are. 
260    </p>
261    <p>
262      Subworkers are currently not supported in Chrome. See <a cl
>ass="external" href="http://code.google.com/p/chromium/issues/det 
>ail?id=31666" title="http://code.google.com/p/chromium/issues/det 
>ail?id=31666">crbug.com/31666</a> . 
263    </p>
264    <h2 id="Embedded_workers">
265      Embedded workers
266    </h2>
267    <p>
268      There is not an "official" way to embed the code of a worke
>r within a web page as for the {{ HTMLElement("script") }} elemen 
>ts. But a {{ HTMLElement("script") }} element which does not have 
> a <code>src</code> attribute and has a <code>type</code> attribu 
>te that does not identify an executable mime-type will be conside 
>red a data block element, that JavaScript could use.&nbsp; "Data  
>blocks" is a more general feature of HTML5 that can carry almost  
>any textual data. So, a worker could be embedded in this way: 
269    </p>
270    <pre class="brush: html">
271&lt;!DOCTYPE html&gt;
272&lt;html&gt;
273&lt;head&gt;
274&lt;meta charset="UTF-8" /&gt;
275&lt;title&gt;MDN Example - Embedded worker&lt;/title&gt;
276&lt;script type="text/js-worker"&gt;
277  // This script WON'T be parsed by JS engines because its mime-t
>ype is text/js-worker. 
278  var myVar = "Hello World!";
279  // Rest of your worker code goes here.
280&lt;/script&gt;
281&lt;script type="text/javascript"&gt;
282  // This script WILL be parsed by JS engines because its mime-ty
>pe is text/javascript. 
283  function pageLog (sMsg) {
284    // Use a fragment: browser will only render/reflow once.
285    var oFragm = document.createDocumentFragment();
286    oFragm.appendChild(document.createTextNode(sMsg));
287    oFragm.appendChild(document.createElement("br"));
288    document.querySelector("#logDisplay").appendChild(oFragm);
289  }
290&lt;/script&gt;
291&lt;script type="text/js-worker"&gt;
292  // This script WON'T be parsed by JS engines because its mime-t
>ype is text/js-worker. 
293  self.onmessage = function (oEvent) {
294    self.postMessage(myVar);
295  };
296  // Rest of your worker code goes here.
297&lt;/script&gt;
298&lt;script type="text/javascript"&gt;
299  // This script WILL be parsed by JS engines because its mime-ty
>pe is text/javascript. 
300 
301  // In the future...:
302  // var oBuilder = new BlobBuilder();
303  // ...but for now...:
304  var oBuilder = new MozBlobBuilder();
305  Array.prototype.forEach.call(document.querySelectorAll("script[
>type=\"text\/js-worker\"]"), function (oScript) { oBuilder.append 
>(oScript.textContent); }); 
306 
307  // Creating a new document.worker property containing all our "
>text/js-worker" scripts. 
308  document.worker = new Worker(window.URL.createObjectURL(oBuilde
>r.getBlob())); 
309  // Note: window.webkitURL.createObjectURL() in Chrome 10+.
310 
311  document.worker.onmessage = function (oEvent) {
312    pageLog("Received: " + oEvent.data);
313  };
314 
315  // Start the worker.
316  window.onload = function() { document.worker.postMessage(""); }
>; 
317&lt;/script&gt;
318&lt;/head&gt;
319&lt;body&gt;&lt;div id="logDisplay"&gt;&lt;/div&gt;&lt;/body&gt;
320&lt;/html&gt;
321</pre>
322    <div class="note">
323      <strong>Note:</strong> BlobBuilder is not yet avaible. We u
>sed the MozBlobBuilder constructor instead. 
324    </div>
325    <p>
326      The embedded worker is now nested into a new custom <code>d
>ocument.worker</code> property. 
327    </p>
328    <h2 id="Timeouts_and_intervals">
329      Timeouts and intervals
330    </h2>
331    <p>
332      Workers can use timeouts and intervals just like the main t
>hread can.&nbsp; This can be useful, for example, if you want to  
>have your worker thread run code periodically instead of nonstop. 
333    </p>
334    <p>
335      See <a class="internal" href="/en/DOM/window.setTimeout" ti
>tle="En/DOM/Window.setTimeout"><code>setTimeout()</code></a> , <a 
> class="internal" href="/en/DOM/window.clearTimeout" title="En/DO 
>M/Window.clearTimeout"><code>clearTimeout()</code></a> , <a class 
>="internal" href="/en/DOM/window.setInterval" title="En/DOM/Windo 
>w.setInterval"><code>setInterval()</code></a> , and <a class="int 
>ernal" href="/en/DOM/window.clearInterval" title="En/DOM/Window.c 
>learInterval"><code>clearInterval()</code></a> for details. 
336    </p>
337    <h2 id="Terminating_a_worker">
338      Terminating a worker
339    </h2>
340    <p>
341      If you need to immediately terminate a running worker, you 
>can do so by calling the worker's <code>terminate()</code> method 
>: 
342    </p>
343    <pre class="brush: js">
344myWorker.terminate();
345</pre>
346    <p>
347      The worker thread is killed immediately without an opportun
>ity to complete its operations or clean up after itself. 
348    </p>
349    <p>
350      Workers may close themselves by calling their own {{ ifmeth
>od("nsIWorkerScope", "close") }} method. 
351    </p>
352    <h2 id="Handling_errors">
353      Handling errors
354    </h2>
355    <p>
356      When a runtime error occurs in worker, its <code>onerror</c
>ode> event handler is called.&nbsp; It receives an event named <c 
>ode>error</code> which implements the <code>ErrorEvent</code> int 
>erface.&nbsp; The event doesn't bubble and is cancelable; to prev 
>ent the default action from taking place, the worker can call the 
> error event's <a class="internal" href="/en/DOM/event.preventDef 
>ault" title="En/DOM/Event.preventDefault"><code>preventDefault()< 
>/code></a> method. 
357    </p>
358    <p>
359      The error event has the following three fields that are of 
>interest: 
360    </p>
361    <dl>
362      <dt>
363        <code>message</code>
364      </dt>
365      <dd>
366        A human-readable error message.
367      </dd>
368      <dt>
369        <code>filename</code>
370      </dt>
371      <dd>
372        The name of the script file in which the error occurred.
373      </dd>
374      <dt>
375        <code>lineno</code>
376      </dt>
377      <dd>
378        The line number of the script file on which the error occ
>urred. 
379      </dd>
380    </dl>
381    <h2 id="Accessing_the_navigator_object">
382      Accessing the navigator object
383    </h2>
384    <p>
385      Workers may access the <code>navigator</code> object, which
> is available within their scope.&nbsp; It contains the following 
> strings which can be used to identify the browser, just as can b 
>e done from normal scripts: 
386    </p>
387    <ul>
388      <li>
389        <code>appName</code>
390      </li>
391      <li>
392        <code>appVersion</code>
393      </li>
394      <li>
395        <code>platform</code>
396      </li>
397      <li>
398        <code>userAgent</code>
399      </li>
400    </ul>
401    <h2 id="Importing_scripts_and_libraries">
402      Importing scripts and libraries
403    </h2>
404    <p>
405      Worker threads have access to a global function, <code>impo
>rtScripts()</code> , which lets them import scripts or libraries  
>into their scope.&nbsp; It accepts as parameters zero or more URI 
>s to resources to import; all of the following examples are valid 
>: 
406    </p>
407    <pre class="brush: js">
408importScripts();                        /* imports nothing */
409importScripts('foo.js');                /* imports just "foo.js" 
>*/ 
410importScripts('foo.js', 'bar.js');      /* imports two scripts */
411</pre>
412    <p>
413      The browser loads each listed script and executes it. Any g
>lobal objects from each script may then be used by the worker. If 
> the script can't be loaded, <code>NETWORK_ERROR</code> is thrown 
>, and subsequent code will not be executed. Previously executed c 
>ode (including code deferred using {{ domxref("window.setTimeout( 
>)") }}) will still be functional though. Function declarations <s 
>trong>after</strong> the <code>importScript()</code> method are a 
>lso kept, since these are always evaluated before the rest of the 
> code. 
414    </p>
415    <div class="note">
416      <strong>Note:</strong> Scripts may be downloaded in any ord
>er, but will be executed in the order in which you pass the filen 
>ames into <code>importScripts()</code> .&nbsp; This is done synch 
>ronously; <code>importScripts()</code> does not return until all  
>the scripts have been loaded and executed. 
417    </div>
418    <h2 id="Examples">
419      Examples
420    </h2>
421    <p>
422      This section provides several examples of how to use DOM wo
>rkers. 
423    </p>
424    <h3 id="Performing_computations_in_the_background">
425      Performing computations in the background
426    </h3>
427    <p>
428      One way workers are useful is to allow your code to perform
> processor-intensive calculations without blocking the user inter 
>face thread.&nbsp; In this example, a worker is used to calculate 
> Fibonacci numbers. 
429    </p>
430    <h4 id="The_JavaScript_code">
431      The JavaScript code
432    </h4>
433    <p>
434      The following JavaScript code is stored in the "fibonacci.j
>s"&nbsp;file referenced by the HTML&nbsp;in the next section. 
435    </p>
436    <pre class="brush: js">
437var results = [];
438 
439function resultReceiver(event) {
440  results.push(parseInt(event.data));
441  if (results.length == 2) {
442    postMessage(results[0] + results[1]);
443  }
444}
445 
446function errorReceiver(event) {
447  throw event.data;
448}
449 
450onmessage = function(event) {
451  var n = parseInt(event.data);
452 
453  if (n == 0 || n == 1) {
454    postMessage(n);
455    return;
456  }
457 
458  for (var i = 1; i &lt;= 2; i++) {
459    var worker = new Worker("fibonacci.js");
460    worker.onmessage = resultReceiver;
461    worker.onerror = errorReceiver;
462    worker.postMessage(n - i);
463  }
464 };
465</pre>
466    <p>
467      The worker sets the property <code>onmessage</code> &nbsp;t
>o a function which will receive messages sent when&nbsp;the worke 
>r object's&nbsp; <code>postMessage()</code> is called. &nbsp;(Not 
>e that this differs from defining a global <em>variable</em> of t 
>hat name, or defining a <em>function</em> with that name. &nbsp;  
><code>var onmessage</code> and <code>function onmessage</code> wi 
>ll define global properties with those names, but they will not r 
>egister the function to receive messages sent by the &nbsp;web pa 
>ge that created the worker.) &nbsp;This starts the recursion, spa 
>wning new copies of itself to handle each iteration of the calcul 
>ation. 
468    </p>
469    <h4 id="The_HTML.C2.A0code">
470      The HTML&nbsp;code
471    </h4>
472    <pre class="brush: html">
473&lt;!DOCTYPE html&gt;
474&lt;html&gt;
475  &lt;head&gt;
476    &lt;meta charset="UTF-8"  /&gt;
477    &lt;title&gt;Test threads fibonacci&lt;/title&gt;
478  &lt;/head&gt;
479  &lt;body&gt;
480 
481  &lt;div id="result"&gt;&lt;/div&gt;
482 
483  &lt;script language="javascript"&gt;
484 
485    var worker = new Worker("fibonacci.js");
486 
487    worker.onmessage = function(event) {
488      document.getElementById("result").textContent = event.data;
489      dump("Got: " + event.data + "\n");
490    };
491 
492    worker.onerror = function(error) {
493      dump("Worker error: " + error.message + "\n");
494      throw error;
495    };
496 
497    worker.postMessage("5");
498 
499  &lt;/script&gt;
500  &lt;/body&gt;
501&lt;/html&gt;
502</pre>
503    <p>
504      The web page creates a <code>div</code> element with the ID
>&nbsp; <code>result</code> , which gets used to display the resul 
>t, then spawns the worker.&nbsp; After spawning the worker, the < 
>code>onmessage</code> handler is configured to display the result 
>s by setting the contents of the <code>div</code> element, and th 
>e <code>onerror</code> handler is set to <a class="external" href 
>="/en/Debugging_JavaScript#dump()" title="https://developer.mozil 
>la.org/editor/fckeditor/core/editor/en/Debugging_JavaScript#dump( 
>)">dump</a> the error message. 
505    </p>
506    <p>
507      Finally, a message is sent to the worker to start it.
508    </p>
509    <p>
510      <a class="external" href="/samples/workers/fibonacci" title
>="https://developer.mozilla.org/samples/workers/fibonacci/">Try t 
>his example</a> . 
511    </p>
512    <h3 id="Performing_web_I.2FO_in_the_background">
513      Performing web I/O in the background
514    </h3>
515    <p>
516      You can find an example of this in the article <a class="in
>ternal" href="/En/Using_workers_in_extensions" title="En/Using wo 
>rkers in extensions">Using workers in extensions</a> . 
517    </p>
518    <h3 id="Dividing_tasks_among_multiple_workers">
519      Dividing tasks among multiple workers
520    </h3>
521    <p>
522      As multi-core computers become increasingly common, it's of
>ten useful to divide computationally complex tasks among multiple 
> workers, which may then perform those tasks on multiple-processo 
>r cores. 
523    </p>
524    <p>
525      example coming soon
526    </p>
527    <h3 id="Creating_workers_from_within_workers">
528      Creating workers from within workers
529    </h3>
530    <p>
531      The Fibonacci example shown previously demonstrates that wo
>rkers can in fact spawn additional workers.&nbsp; This makes it e 
>asy to create recursive routines. 
532    </p>
533    <h2 id="Browser_Compatibility" name="Browser_Compatibility">
534      Browser compatibility
535    </h2>
536    <p>
537      {{ CompatibilityTable() }}
538    </p>
539    <div id="compat-desktop">
540      <table class="compat-table">
541        <tbody>
542          <tr>
543            <th>
544              Feature
545            </th>
546            <th>
547              Chrome
548            </th>
549            <th>
550              Firefox (Gecko)
551            </th>
552            <th>
553              Internet Explorer
554            </th>
555            <th>
556              Opera
557            </th>
558            <th>
559              Safari (WebKit)
560            </th>
561          </tr>
562          <tr>
563            <td>
564              Dedicated workers
565            </td>
566            <td>
567              3
568            </td>
569            <td>
570              3.5 (1.9.1)
571            </td>
572            <td>
573              10
574            </td>
575            <td>
576              10.60
577            </td>
578            <td>
579              4
580            </td>
581          </tr>
582          <tr>
583            <td>
584              Shared workers
585            </td>
586            <td>
587              5
588            </td>
589            <td>
590              ---
591            </td>
592            <td>
593              ---
594            </td>
595            <td>
596              10.60
597            </td>
598            <td>
599              5
600            </td>
601          </tr>
602          <tr>
603            <td>
604              Passing data using <a href="/en/DOM/The_structured_
>clone_algorithm" title="The structured clone algorithm">structure 
>d cloning</a> .&nbsp; 
605            </td>
606            <td>
607              13
608            </td>
609            <td>
610              8
611            </td>
612            <td>
613              10
614            </td>
615            <td>
616              11.50
617            </td>
618            <td>
619              5.1
620            </td>
621          </tr>
622          <tr>
623            <td>
624              Passing data using&nbsp; <a class="external" href="
>http://dev.w3.org/html5/spec/common-dom-interfaces.html#transfera 
>ble-objects" title="http://dev.w3.org/html5/spec/common-dom-inter 
>faces.html#transferable-objects">transferable objects</a> 
625            </td>
626            <td>
627              17 {{ property_prefix("webkit") }}
628            </td>
629            <td>
630              ---
631            </td>
632            <td>
633              ---
634            </td>
635            <td>
636              ---
637            </td>
638            <td>
639              ---
640            </td>
641          </tr>
642        </tbody>
643      </table>
644    </div>
645    <div id="compat-mobile">
646      <table class="compat-table">
647        <tbody>
648          <tr>
649            <th>
650              Feature
651            </th>
652            <th>
653              Android
654            </th>
655            <th>
656              Chrome for Android
657            </th>
658            <th>
659              Firefox Mobile (Gecko)
660            </th>
661            <th>
662              IE&nbsp;Phone
663            </th>
664            <th>
665              Opera Mobile
666            </th>
667            <th>
668              Safari Mobile
669            </th>
670          </tr>
671          <tr>
672            <td>
673              Dedicated workers
674            </td>
675            <td>
676              ---
677            </td>
678            <td>
679              0.16
680            </td>
681            <td>
682              ---
683            </td>
684            <td>
685              ---
686            </td>
687            <td>
688              11
689            </td>
690            <td>
691              5
692            </td>
693          </tr>
694          <tr>
695            <td>
696              Shared workers
697            </td>
698            <td>
699              ---
700            </td>
701            <td>
702              {{ CompatNo() }}
703            </td>
704            <td>
705              ---
706            </td>
707            <td>
708              ---
709            </td>
710            <td>
711              ---
712            </td>
713            <td>
714              ---
715            </td>
716          </tr>
717          <tr>
718            <td>
719              Passing data using <a href="/en/DOM/The_structured_
>clone_algorithm" title="The structured clone algorithm">structure 
>d cloning</a> .&nbsp; 
720            </td>
721            <td>
722              ---
723            </td>
724            <td>
725              0.16
726            </td>
727            <td>
728              ---
729            </td>
730            <td>
731              ---
732            </td>
733            <td>
734              ---
735            </td>
736            <td>
737              ---
738            </td>
739          </tr>
740          <tr>
741            <td>
742              Passing data using&nbsp; <a class="external" href="
>http://dev.w3.org/html5/spec/common-dom-interfaces.html#transfera 
>ble-objects" title="http://dev.w3.org/html5/spec/common-dom-inter 
>faces.html#transferable-objects">transferable objects</a> 
743            </td>
744            <td>
745              ---
746            </td>
747            <td>
748              ---
749            </td>
750            <td>
751              ---
752            </td>
753            <td>
754              ---
755            </td>
756            <td>
757              ---
758            </td>
759            <td>
760              ---
761            </td>
762          </tr>
763        </tbody>
764      </table>
765    </div>
766    <h2 id="See_also">
767      See also
768    </h2>
769    <ul>
770      <li>{{ spec("http://dev.w3.org/html5/workers/", "File API S
>pecification: Web Workers", "ED") }} 
771      </li>
772      <li>
773        <code><a class="internal" href="/en/DOM/Worker" title="En
>/DOM/Worker">Worker</a></code> interface 
774      </li>
775      <li>
776        <code><a class="internal" href="/en/DOM/SharedWorker" tit
>le="En/DOM/SharedWorker">SharedWorker</a></code> interface 
777      </li>
778      <li>
779        <a href="/en/DOM/Worker/Functions_available_to_workers" t
>itle="En/DOM/Worker/Functions available to workers">Functions ava 
>ilable to workers</a> 
780      </li>
781      <li>
782        <a class="external" href="http://www.html5rocks.com/en/tu
>torials/workers/basics/#toc-enviornment-subworkers" title="http:/ 
>/www.html5rocks.com/en/tutorials/workers/basics/#toc-enviornment- 
>subworkers">HTML5Rocks - The Basics of Web Workers</a> 
783      </li>
784      <li>
785        <code><a class="external" href="http://code.google.com/p/
>chromium/issues/detail?id=127990" title="Chrome has Problems with 
> many workers">Chrome has problems when using too many workers</a 
>></code> 
786      </li>
787    </ul>
788    <p>
789      {{ HTML5ArticleTOC() }}
790    </p>
791    <p>
792      {{ languages ( {"es": "es/Usar_web_workers", "ja": "ja/Usin
>g_web_workers"} ) }} 

Back to History