An Introduction to Web Workers JavaScript API

Web Workers is a JavaScript API that allows you to run scripts in a separate thread from the main one. It can come in handy when you don’t want any hindrance in the execution of the main scripts, due to background-esque scripts.

The Web Workers API is supported in almost all browsers, for more detailed information, have a look at the CanIUse docs. Before getting into the code, let’s see a couple of scenarios where you might want to use this API so that you can get an idea of what I meant by background-esque scripts.

Use cases

Let’s say there’s a script that fetches and processes a file. If a file is considerably large it’ll take a long time to be processed! Which might stall other scripts that were invoked later from getting executed.

However, if the file processing is moved to a background thread, known as the worker thread, other events won’t be blocked until the former one is over.

The script executed in a background worker thread is known as the worker script or just the worker.

For another example, imagine there is a big form, arranged in tabs. It’s scripted in a way that updating controls in one tab affects some of the controls in others.

If the update of the other tabs takes some time the user can’t continuously use the current tab without its events being put on hold. This might freeze the UI, to user’s dismay.

Since a user won’t be seeing the other tabs while filling out a current one, you can update the controls of the other tabs in a background thread. This way, the user can continue using the current tab he is filling out, without any of its scripts being blocked by the update process of controls in other tabs.

Likewise, if you find a scenario where a script might block a user from using the user interface until its execution is done, you might consider moving it to a worker thread, so that it could be executed in the background.

Scopes and types of workers

The Web Workers API is probably one of the simplest APIs to work with. It has pretty straightforward methods to create worker threads and communicate with them from the main script.

The global scope of a worker thread is in a different context from the main thread. You can’t access the methods and properties of window object such as alert() inside a worker thread. You also can’t change the DOM directly from a worker thread.

However, you can use many APIs that come under window, for instance Promise and Fetch, in your worker thread (see the full list).

You can also have nested worker threads: worker threads created from another worker thread. A worker created by another one is called a subworker.

There are also many types of workers. The two main ones are dedicated and shared workers.

Dedicated workers belong to the same browsing context that their main thread belongs to. Shared workers, however, are present in a different browsing context (for instance, in an iframe) from the main script. In both cases, the main script and the workers have to be in the same domain.

The example in this tutorial will be about dedicated worker, which is the most common type.

API methods

See the below diagram for a quick overview of all the main methods that constitute the Web Workers API.

Methods of the Web Worker API

The Worker() constructor creates a dedicated worker thread and returns its reference object. Then, we use this object to communicate with that specific worker.

The postMessage() method is used in both the main and worker scripts to send data to each other. The sent data is then received on the other side by the onmessage event handler.

The terminate() method terminates a worker thread from the main script. This termination is immediate: any current script execution and pending scripts will be cancelled. The close() method does the same thing, but it’s called by the worker thread closing itself.

Example code

Now, let’s see some sample code. The index.html page holds the main script inside a <script> tag, while the worker script is held in a JavaScript file called worker.js.

<button>Click me</button>
<!-- main script goes here -->

We start with the creation of the worker thread from the main script.

w = new Worker('worker.js');

The Worker() constructor takes the URL of the worker file as its argument.

Then, we add an event handler for the onmessage event of the newly created worker instance to receive data from it. The data property of the e event will hold the received data.

w = new Worker('worker.js');
w.onmessage = (e)=>{
  console.log(`Received from worker: ${}`);

Now, we use postMessage() to send some data to the worker thread on the click of a button. The postMessage() method can take two arguments. The first can be of any type (string, array…). It’s the data to be sent to the worker thread (or to the main script, when the method is present in the worker thread).

The second, optional parameter is an array of objects that can be used by the worker threads (but not by the main script, or vice-versa). These kinds of objects are called Transferable objects.

document.querySelector('button').onclick = ()=>{

I’m just sending a string value to the worker thread.

In the worker thread, we need to add an onmessage event handler that will receive the data sent to it by the main script on button click. Inside the handler, we concatenate the received string with another and send the result back to the main script.'worker created');
onmessage = (e)=>{
  postMessage(`Hi ${}`);

Unlike in the main script where we had to use the w reference object to refer to the specific worker thread on which the script then uses the onmessage and postMessage methods, there’s no need for a reference object in the worker thread to point to the main thread.

The code works as follows. When the browser loads index.html, the console will show the "worker created" message as soon as the worker() constructor is executed in the main thread, creating a new worker.

When you click the button on the page, you’ll get the "Received from worker: Hi john" message in the console, which is the string that was concatenated in the worker thread with the data sent to it, and then was sent back to the main script.