Chapter 4. Inline Workers

There are cases in which you will want to create your Worker script “on the fly” in response to some event that your web app has fired. In other cases, you might want to have a self-contained page without having to create separate Worker files. Sometimes, you might wish to have your entire web app encapsulated in one page: you want to be able to fetch the app with one Ajax call, or bundle it as a Chrome extension. Inline Workers support these use cases.

The example below shows how we can use the new BlobBuilder[6] interface to inline your Worker code in the same HTML file.

Example 4-1. Creating an inline Worker with a javascript/worker type

<script id="worker1" type="javascript/worker">
// This script won't be parsed by JS engines because its type is JavaScript/worker.
// Simple code to calculate prime number and send it back to the parent page.
      self.onmessage = function(e) {
      self.postMessage("<h3>Worker: Started the calculation</h3><ul>");
        var n = 1;
        search: while (n < 500) {
          n += 1;
          for (var i = 2; i <= Math.sqrt(n); i += 1)
            if (n % i == 0)
              continue search;
          // found a prime!
          postMessage("<li>Worker: Found another prime: " + n + "</li>");
        }
        postMessage("</ul><h3>Worker: Done</h3>");
      }
</script>

You can see that we are using javascript/worker in the type so the JavaScript engine won’t parse this code (yet). Next, we calculate the prime numbers up to 500 and send messages to the parent page after each prime is found.

In the main page, we will create a BlobBuilder with the code we have under the script Id “worker1.” Then, by using window.URL.createObjectURL we will create a new File (or Blob) that represents our data. Firefox and Chrome both have the ability to use window.URL; however, in Chrome/Safari/other WebKit browsers, we will use window.webkitURL.

Example 4-2. Creating a Worker using BlobBuilder

<script>
     // Creating the BlobBuilder and adding our Web Worker code to it.
     var bb = new (window.BlobBuilder || window.WebKitBlobBuilder ||
                   window.MozBlobBuilder)();
     bb.append(document.querySelector('#worker1').textContent);

     // Creates a simple URL string which can be used to reference
     // data stored in a DOM File / Blob object.
     // In Chrome, there's a nice page to view all of the created
     // blob URLs: chrome://blob-internals/

     // OurUrl enable our code to run in Chrome and Firefox.
     var ourUrl = window.webkitURL || window.URL;
     var worker = new Worker(ourUrl.createObjectURL(bb.getBlob()));

     worker.onmessage = function(e) {
       status(e.data);
     }
     worker.postMessage();
</script>

Example 4-3 includes the HTML page with some elements that show what goes on while the Web Worker is finding prime numbers. The main disadvantage to this technique is that it will be harder to debug your Web Worker JavaScript code. One way to be more productive would be to test your Web Worker as an external file. Then, only after you are happy with the results, put it back in the page as an inline Web Worker.

Results of the inline Worker hunting for prime numbers

Figure 4-1. Results of the inline Worker hunting for prime numbers

Example 4-3. Inline Web Worker

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Web Worker: Inline Worker example</title>
    <meta name="author" content="Ido Green">
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
  </head>

  <style>
    #status {
      background: lightGreen;
      border-radius: 15px;
      padding: 15px;
      overflow: auto;
      height:450px;
    }
    article {
      background: lightsalmon;
      border-radius: 15px;
      padding: 15px;
      margin-bottom: 15px;
    }
  </style>

  <body>
    <h1>Web Worker: Inline Worker example</h1>

    <article>
      This is an example for inline Worker that we created "on the fly" without the need to fetch our JavaScript code of the Worker from another file.<br/>
      It is a useful method to create a self-contained page without having to create a separate Worker file.<br/>
      With the new BlobBuilder interface, you can "inline" your Worker in the same HTML file as your main logic by creating a BlobBuilder and appending the Worker code as a string.
    </article>

    <div id="status"></div>

    <script id="worker1" type="JavaScript/worker">
      // This script won't be parsed by JS engines because its type is JavaScript/worker.
      // We have here some simple code to calculate prime numbers and send them back to the parent page.
      self.onmessage = function(e) {
      self.postMessage("<h3>Worker: Started the calculation</h3><ul>");
        var n = 1;
        search: while (n < 500) {
          n += 1;
          for (var i = 2; i <= Math.sqrt(n); i += 1)
            if (n % i == 0)
              continue search;
          // found a prime!
          postMessage("<li>Worker: Found another prime: " + n + "</li>");
        }
        postMessage("</ul><h3>Worker: Done</h3>");
      }
    </script>

    <script>
      function status(msg) {
        $("#status").append(msg);
      }

      // Creating the BlobBuilder and adding our Web Worker code to it.
      //new BlobBuilder();
      var bb = new (window.BlobBuilder || window.WebKitBlobBuilder)();
      bb.append(document.querySelector('#worker1').textContent);

      // creates a simple URL string that can be used to reference
      // data stored in a DOM File / Blob object.
      // In Chrome, there's a nice page to view all of the
      // created blob URLs: chrome://blob-internals/
      var worker = new Worker(window.webkitURL.createObjectURL(bb.getBlob()));
      worker.onmessage = function(e) {
        // pass the information we received from the worker and print it
        status(e.data);
      }
      worker.postMessage(); // Start the worker.
    </script>
  </body>
</html>

Get Web Workers now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.