# Quick Tip: JavaScript Web Workers Move Hard Work to the Background

##### Tutorial Details
• Difficulty: Intermediate
• Platform: HTML5
• Language: Javascript
• Software Required: Any text editor
• Estimated Completion Time: 20 minutes

A web worker is a JS script that runs in the background, separately from other scripts, allowing us to introduce threading in our web apps. Although not part of the HTML5 spec, web workers can be used with HTML5 apps. In this Quick Tip, we’ll take a look at how to use them.

## Introduction to Web Workers

In the land of HTML5 we have some very interesting APIs available. Some of them – like Web Workers – are useful for increasing performance, which is very important for both apps and games. But how do web workers… well, work?

Every instance of a web worker creates another thread, in which your JavaScript runs. You instantiate one like so:

var worker = new Worker('filename.js');


Here, ‘filename.js’ is the name of file containing your script. Because Workers are individual environments, you can’t use code embedded directly in HTML; you must use a separate file.

## Communication: Sending and Receiving Data

Workers don’t have access to the page DOM or the global object, so how do they communicate with the site? It’s simple. When you want to send some data from your page to a Worker, you invoke postMessage().

This takes one parameter: data to send, which can be either a string or a JSON parsable object (which means that you can’t pass functions or circular references, or you will get a DOM_EXCEPTION). On some browsers there is a problem with objects, so it’s always better to manually parse the object with JSON.parse() so you don’t have to worry about incomplete implementations.

The same goes if you are sending data from a Worker to the page: just invoke postMessage() on self, which refers to the Worker’s global scope. (You do this inside the Worker’s script, of course).

Then, to receive the data you have to attach an onmessage event handler. There are two ways of doing that, just like with regular events for DOM elements; you can either directly assign some function to the Worker’s onmessage property, or you can use addEventListener().

// First way:
worker.onmessage = function (e) {
console.log(e.data); // Log the data passed
}

// Second way:
console.log(e.data); // Log the data passed
});


It’s your choice which method to use. Either way, the function’s parameter will be an event object, and the data you sent using postMessage() will be passed via the data property of this event.

## External Scripts and Libraries

Okay, but what if we have to use some external library? We don’t have access to the DOM or the global scope, so we can’t just inject the script.

Of course we don’t need to – there is a function for that. It is called importScripts() and it accepts one or more arguments: script names to load inside the scope of the Worker. You should be aware that scripts passed into this function are loaded in a random order, but they will be executed as specified and script execution will be paused until they are loaded.

importScripts('one-lib.js'); // Loads one script
importScripts('first-lib.js', 'second-lib.js', 'third-lib.js'); // Loads three scripts


You can use importScripts anywhere in your code, making it easy to create JSONP requests inside the Workers, as we will do in the following example.

## Example: Workers in Action

Right, so now you probably want to see a Worker in action. Instead of showing something fairly useless, like obtaining primes or Fibonacci numbers, I’ve decided to make something that you will maybe use after a few changes.

The example script (I’ve included the Worker’s code only, the rest is easy to do) will get the last 100 Tweets from @envatoactive (we need to set the count to 121 instead of 100, as Tweeter API is sending fewer tweets than requested – don’t ask me why, I don’t know).

Here’s the code that would go inside the actual Web Worker script file:

// Helper function for processing the data
var process = function (data) {
// Iterate through the data; we know it's an array, so it's safe
for (var i = 0, v; v = data[i]; i++) {
// And pass Tweet's text to the page
self.postMessage({ text: v.text });
}
// After work is done, let the page know
self.postMessage("finished");
}

// Attach event listener to handle messages
// Check if command sent was 'start'
// Not necessary here, but may be useful later
if (event.data == "start") {
// Reply to the page that we started the work
self.postMessage("started");
// Core of the script, get the Tweets
// The callback parameter specifies the function to execute after the request is done
// (We call the process() function, defined above.)
// Count needs to be 121 because Tweeter API is sending lower amount of data than requested
}
});


It should be easy to understand how this all works from the comments. This lets your app load all the tweets in the background, using a separate thread.

Now try inserting the following equivalent code, which doesn’t use web workers, into the head of an empty page instead, and note the delay. (It’s still small, but imagine if you were getting not 100 but 100,000 Tweets):

<script type="text/javascript">
var process = function (data) {
// Iterate through the data; we know it's an array, so it's safe
for (var i = 0, v; v = data[i]; i++) {
// And log Tweet's text to the console
console.log(v.text);
}
}
</script>


## Conclusion

As you can see, web workers offer you a simple way to remove lag from your GUI and move complicated calculations or networking to separate threads.

I hope you learned something new from this article – maybe you will use Workers in your next project? If you have any questions or problems please comment below.

• http://www.webone.gr Κατασκευή ιστοσελίδων

Hi

Thanks for interesting and informative article – tutorial.

I would like to ask the following: Is the performance the only benefit that Web Workers offer? If that is the case, I guess that every heavy loaded website might benefit from it.

But what about normal websites? Will they be able to see any even slight performance improvement?

Regards