65.9K
CodeProject is changing. Read more.
Home

Working with Inline Web Workers

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (5 votes)

Jan 30, 2012

CPOL

3 min read

viewsIcon

28051

This post is going to explain what are inline Web Workers and how to create them.

Working with Inline Web Workers

Working with Inline Web WorkersIn the past I wrote a post about what are Web Workers. In short, Web Workers enable web developers to run JavaScript code in the background which might help to increase web page performance. This post is going to explain what are inline Web Workers and how to create them.

Inline Web Workers

When dealing with Web Workers, most of the times you will create a separate JavaScript file for the worker to execute. Inline Web Workers are Web Workers which are created in the same web page context or on the fly. The reason for doing such a thing is obvious, sometimes we want to reduce the number of requests that the page perform and sometimes we need to create some functionality on the fly. Executing external JavaScript files can’t help us with that.

There are two kinds of inline Web Workers:

  • Page inline worker – The worker's JavaScript code is created inline inside the web page. In this case you will use a script tag with an ID and a JavaScript/worker type. the type will indicate to the browser not to parse the written inline JavaScript and it will refer to it as string. Here is an example for such script tag:
  • <script id="worker" type="javascript/worker">
       postMessage('worker sent message');
    </script>

    Later you will be able to retrieve the script by its id and use its textContent property to extract the worker body.

  • On the fly worker – The worker’s JavaScript code is provided by an external source as string.

In both of the cases, in order to run the worker you will have to create a blob object and a blob URL.

Creating the Web Worker

The main way to create an inline Web Worker is using the BlobBuilder object which was added by the HTML5 File API. BlobBuilder enables us to create a blob object from a given string. It includes two main functions – the append function and the getBlob function. The append function adds data into the underlining blob and the getBlob returns the created blob object.

After you create a blob object from the inline worker implementation you will have to create a URL from it. The reason is that Web Workers gets a URL as parameter. For our rescue, HTML5 defines another two functions in the File API – createObjectURL and revokeObjectURL. Both of the functions exists in the window.URL object. Blob URLs are a unique URL which is created and stored by the browser up until the document is unloaded. The createObjectURL function gets a blob object and returns the blob URI which can be used. The revokeObjectURL function is used to release a created blob URL. If you are creating a lot of blob URLs you should use the revokeObjectURL in order to release references to blob URLs which aren’t in use.

Let's take a look at an example of creating an inline Web Worker:

var bb = new BlobBuilder();
bb.append(workerBody);
var workerURL = window.URL.createObjectURL(bb.getBlob());
var worker = new Worker(workerURL);

In the example, a BlobBuilder is created and a workerBody is appended to it. The workerBody can be any piece of code that you want to run inside a Web Worker. After you create the in-memory blob you will use the createObjectURL function to create the the blob URL and use it as a parameter to the Web Worker. If you want to use the script tag from the first code example you can write the following code:

var bb = new BlobBuilder();
bb.append(document.querySelector('#worker').textContent);
var workerURL = window.URL.createObjectURL(bb.getBlob());
var worker = new Worker(workerURL);

The Full Example

I wanted to create an experimental code example to show how to encapsulate the previous inline Web Workers implementation inside a JavaScript object and use it so here it goes:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Inline WebWorker</title>
    <meta charset="utf-8" />
    <script>
        // create a namespace for the object
        var workerHelpers = workerHelpers || {};
        
        // set the blob builder and window.URL according to the browser prefix if needed
        var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
        window.URL = window.URL || window.webkitURL;
 
        workerHelpers.InlineWorkerCreator = function () {
        };
 
        workerHelpers.InlineWorkerCreator.prototype = function () {
            createInlineWorker = function (workerBody, onmessage) {
                if (BlobBuilder) {
                    var bb = new BlobBuilder();
                    bb.append(workerBody);
 
                    var workerURL = window.URL.createObjectURL(bb.getBlob());
                    var worker = new Worker(workerURL);
                    worker.onmessage = onmessage;
                    return workerURL;
                }
                else {
                    console.log('BlobBuilder is not supported in the browser');
                    return;
                }
            },
            releaseInlineWorker = function (workerURL) {
                window.URL.revokeObjectURL(workerURL);
            };
 
            return {
                createInlineWorker: createInlineWorker,
                releaseInlineWorker: releaseInlineWorker
            };
        } ();
 
        window.addEventListener('DOMContentLoaded', function () {
            var creator = new workerHelpers.InlineWorkerCreator();
            var workerURL = creator.createInlineWorker('postMessage(\'worker sent message\');', function (e) {
                console.log("Received: " + e.data);
            });
            console.log(workerURL);
 
            // release the URL after a second
            setTimeout(function () { creator.releaseInlineWorker(workerURL); }, 1000);
        }, false);        
    </script>
</head>
<body>
</body>
</html>

Summary

In the post I explained the reason to create inline Web Workers. I also showed how to create an inline Web Worker and provided an implementation for a JavaScript object that can be used to do that. 

I’ll appreciate any comments about the provided code.