To run tasks that take a long time to complete, we need a way to run them in the background.
Web workers are the way to do that. They live in their own context within the browser. Therefore, they don’t have access to the DOM and have their own global variable, self
.
A web worker can’t access the window
object, but we still use many things that are parts of it like WebSockets and IndexedDB.
In this article, we’ll look at how to create a basic web worker that can send messages between workers and other scripts.
Characteristics of Web Workers
Web workers allow us to send messages between them and other scripts. Non-worker scripts can listen to messages that are emitted by workers by attaching handlers for messages.
To send messages, we use the postMessage()
method. The message can be accessed via the Message
event’s data property. Message
event objects are passed into the event handler of the onmessage
handler.
Workers can spawn new workers, as long as they are hosted within the same origin as the parent page. Workers may also use XmlHttpRequest
for network I.O, with the exception that the responseXML
and channel
attributes on XMLHttpRequest
always return null
.
In addition to dedicated workers, there are also other kinds of workers:
- Shared workers are workers that can be used by multiple scripts in different windows, IFrames, etc, as long as they’re in the same domain as the worker. They are more complex than dedicated workers in that scripts must communicate via an active port.
- Service workers act as proxy services that sit between web apps, the browser, and the network. They are intended to create effective offline experiences. They intercept network requests and take appropriate actions based on whether the network is available.
- Chrome workers are a Firefox-only type of worker that we can use when developing add-ons and want to use workers in extensions.
- Audio workers provide the ability to direct scripted audio processing to be done inside a web worker context.
Photo by David Siglin on Unsplash
Creating a Simple Dedicated Worker
We can create a dedicated worker by creating a simple worker script and then have other scripts communicate with it.
For example, we can create a dedicated worker that takes values from two inputs and then compute the result by adding them and sending it back to the screen.
First, we create the HTML for getting the input values as follows:
Then, in main.js
, we add keyup
event handlers to the inputs to send the values to our dedicated worker as follows:
We also add the onmessage
event handler to receive the message from the worker, which we’ll add to worker.js
to get the message back from it in the following piece of code:
worker.onmessage = e => {
result.textContent = e.data;
};
Finally, we create the worker code in worker.js
as follows:
The code above gets the message from main.js
, where we called postMessage
. Whatever we passed to postMessage
will be in the e
parameter and we can get the data from there.
Then, in this file, we get the two numbers we passed in with the data
property on the first line of the function.
We then check if both numbers are numbers and if they are, we add them together and then send the sum back to main.js
with postMessage
after we compute the sum and put the result in the workerResult
string.
In the end, we should get something like the following:
As long as the dedicated worker script is in the same domain as our other scripts, it’ll run.
The Worker
constructor also takes an option object with the following options:
type
: A string specifying the type of worker to create. The value can beclassic
ormodule
and defaults toclassic
.credentials
: A string specifying the type of credentials to use for the worker. The value can beomit
(no credentials required),same-origin
, orinclude
. If it’s not specified, thetype
isclass
, thenomit
is the default.name
: A string specifying the identifying name for theDedicatedWorkerGlobalScope
representing the scope of the worker. It’s mainly used for debugging.
The constructor will throw a SecurityError
if it’s not allowed to start workers, like if the URL is invalid or the same-origin policy is violated.
NetworkError
is raised if the MIME type of the worker script is incorrect.SyntaxError
is raised is the worker’s URL can’t be parsed.
Creating dedicated workers is simple. They let us run background tasks. Communication between workers and other scripts is by sending messages back and forth.
Web workers have their own context so they can’t use the window
object or access the DOM.