Web Workers in JavaScripts.
How can we achieve concurrency in Javascript?
Hey Guys, In this article I will be talking about one of the most interesting features of JavaScript i.e Web Workers. Javascript has many bottlenecks like performance, browser compatibility, and accessibility. Just like this one of the drawbacks is its single-threaded nature, JavaScript is unable to perform multiple tasks at a single time. For Example let’s say you are building a large-scale web application that involves continuous UI Events, Query and handle a huge amount of API data, and handling DOM.
Unfortunately, we can not handle all of this simultaneously because script execution happens in a single thread environment. We do try to replicate concurrency using setTimeout(), setInterval(), XMLHttpRequest, and event handlers. They do provide asynchronous nature but it is not the same thing. Asynchronous events are processed after the currently executing script has yielded.
Here comes the concept called Web Workers, which provides you the way to execute multiple scripts concurrently, handle huge API data, and do some computationally intensive tasks without blocking the UI or other scripts that handle UI. There are several types of Web Workers:-
- Dedicated Web Workers — This one is used as my only single script.
- Shared Web Workers — They are shared among multiple scripts across the windows or Iframes, only if the web worker and scripts domain are the same.
- Service Workers — These are special kinds of web Workers, they act as a proxy between browser(client) and network. They can incept the outgoing requests, they allow us to use Push(Push Notification) and Background Sync API.
In this article we will be talking about Dedicated Web Workers, soon in upcoming articles, I will be covering Shared and Service Worker API.
Web worker does not have the access to the global context(global scope object), the window object is available but not directly accessible, they are accessible through the shared mixin WindowOrWorkerGlobalScope, with the help of this mixin, they have their own WorkerGlobalScope(derived). In simple terms, you can not access javascript globals in web Workers you must use WorkerGlobalScope, some of the common accessible API’s are, atob(), btoa(), clearInterval(), clearTimeout(),dump() , setInterval(), setTimeout(), Here is the list of all the available API.
Yeah! As we know Web Workers works in an isolated thread, that is why they needed to write in a separate file, before doing any code we need to create a Worker Object on our main page, like this
let worker = new Worker('web-worker.js');
The web-worker.js
is your worker file(path to the file. here it is in the root directory), the worker will not start working until your given file is completely downloaded and executed, if your file does not exist or fail to load, your worker will fail silently(Sad but True😥). The Communication between the Worker and the parent page is done via, Event Model and postMessage() method, postMessage() accepts a single parameter a JSON Object or a String.
Let me give you a simple example, Here is our main script(Parent Script)
// main.js
let worker = new Worker('web-worker.js');
worker.addListener('message',(e) => {
console.log('Hey! Workers Said : ', e.data);
},false);
worker.postMessage('This message is from Parent to Web Worker');
Our web worker code will look something like this,
// web-worker.js
self.addEventListener('message', function(e) {
self.postMessage(e.data);
}, false);
Explanation
Here postMessage()
from main.js
sends the message to the web worker, and our worker handles that message by defining onmessage
event and vice versa.
Let’s write a simple program, We will have three buttons, START THE WROK
POST MESSAGE
, and STOP THE WORK
The main.js
, which will be our parent for web worker will look something like this,
And our worker.js
will be something like this...
Here Starting the work means we will register our web worker with the client, and the send message will send the message to the worker, in response web worker can sending the appropriate message.
In our main.js
we are continuously listening for the message from the worker. We can stop the work using the worker.terminate()
API, I have added a delay of 100ms to get the response from the worker as well.
Here how it actually looks like,
Originally published at https://adarsh-thakur.hashnode.dev.