Introduction to Web Workers aka Multi-Threading in browser
Tags: webdevelopement, browser, web, javascript
Published: 2021-01-11 12:51:31

## Introduction

Web Workers are scripts which run in a separate thread in the background.

> Web Workers are a simple means for web content to run scripts in background threads. The worker thread can perform tasks without interfering with the user interface. (from MDN docs)

Javascript is a single threaded programming language, which means it runs instructions step by step <strong>sequentially</strong>.
If the code is executing some expensive task which takes a lot of time. Then, no other javascript code can execute until the control comes out of that step. This is because the current thread is busy executing that step and javascript is a <strong>single threaded </strong> language.
While that step is being executed, no javascript can execute making the UI un-responsive for task requiring javascript, which is obviously a bad user experience.

We wouldn't have faced this problem if javacsript was multi-threaded. It's not though. What if we can create threads using the <i>web browser</i>? ....Web Workers were born.

Each Web Worker runs in a separate <strong>OS thread </strong>and <strong>execution context</strong>.

Lets Start Coding!

```javascript
// Check if the Web Workers are supported by the browser
if (window.Worker) {
  // Create a new Web Worker
 //Pass the URI of the script which has to run as a web worker to the Worker Constructor
  const myWorker = new Worker('worker.js'); 
}
```
Inside the worker script (worker.js in this case) can be as simple as a console.log
```javascript 
console.log("Running in a separate thread");
```
The main and the worker threads interact through **Messages**.

**self** in the web worker refers to the Worker Execution Context instance. We'll come back to self later again.

### Sending Messages
We send message from main thread to worker thread through **postMessage** method of the worker.
Message from the worker script can be sent to main thread by simply calling postMessage(message) or self.postMessage(message)

###  Listening to Messages
The onmessage method of the worker instance fires when that worker has sent a message to the main thread.
The self.onmessage or onmessage function in the worker script fires when the main thread has sent a message.
The onmessage event listener function accepts a instance of [MessageEvent](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent).

<small>app.js</small>
```javascript 
const myWorker = new Worker('worker.js'); 
console.log("[Inside Main thread] Sending Message to Worker thread");
myWorker.postMessage("Hello Web Worker");
myWorker.onmessage = function (message) {
  console.log("[Inside Main thread] Message sent by Web Worker - ",message.data);
}
```
<small>worker.js</small>
```javascript 
//onmessage is implicitly self.onmessage
onmessage = function (message){
  console.log("[Inside WebWorker] Message sent by Main thread - ", message.data);
 console.log("[Inside WebWorker] Sending Message to Main Thread");
  postMessage("Hello Main Thread");
}
```
<small>Output ( Console logs )</small>
```
[Inside Main thread] Sending Message to Worker thread
[Inside WebWorker] Message sent by Main thread - Hello Web Worker
[Inside WebWorker] Sending Message to Main Thread
[Inside Main thread] Message sent by Web Worker - Hello Main Thread
```

You can't access all Browser API inside the web worker script and that's for good. You have access to browser Api like IndexedDB, Web Sockets, inside the web worker. You can't directly manipulate or access DOM. [Complete list of Browser api supported inside web worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Functions_and_classes_available_to_workers).

## Types of Web Workers
+ Dedicated Web Worker (What we saw earlier)
+ Shared Web Worker 

### Dedicated Web Worker
The web worker instance can be accessed only by the script created it.
### Shared Web Worker
The web worker instance can be accessed by any script.

## Further Readings
Learn more about Web Workers from [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers)