Web workers

Web workers work in a separate thread and does not block the main thread

<!doctype html>
<html>
<head><titleweb worker example </title></head>
<body>
    <button id="backgroundBtn"change background </button>
    <button id="calculateBtn"calculate </button>
    <script>
        const backgroundBtnEle = document.getElementById("backgroundBtn");
        const calculateBtnEle = document.getElementById("calculateBtn");
        
        backgroundBtnEle.addEventListener("click", (event=> {
            document.body.style.background === "green" ?
            document.body.style.background = "gold" : document.body.style.background = "green"
        })
        calculateBtnEle.addEventListener("click", (event=> {
            let total = 0;
              for(let i=0i<100000000i++) {
                for(let j=0j<100j++) {
                  total = total - i + j;
                }
              }
            alert("Total is: "total);
        })
    </script>
</body>
</html>

Here, once "calculate" button is clicked, the screen freezes and does not allow clicking of "change background" button. This is because the main thread is blocked.

Let us move the calculation portion to a web worker.

Before trying to implement a web worker, make sure you are serving files from a server such as node.

Quick setup:

npm i express

npm i ejs (view engine as you will render an html file)

server.js

const express = require('express')
const app = express();

app.use(express.static('public'));
app.set('view engine''ejs');

app.get("/", (req,res=> {
  res.render("index");
});

app.listen('3000', ()=> console.log('listening at 3000'));

Note: Make sure you have renamed the ".html" file to ".ejs". This should be inside "views" folder

the "worker.js" file that will be created next has to go inside "public" folder

1. Create a new webworker 

create a file public -> worker.js. 
Call this file and create a new worker pointing to this file

<script src="../worker.js"></script>
const worker = new Worker("../workder.js");
worker.postMessage("hello from main thread");

And in worker.js file:

In any worker file, the global object is the worker itself. Just like how the glbal object is window in other cases. So you can either use self.onmessage or just onmessage

onmessage = (msg=> {
  console.log("Msg received from main thread"msg.data);
  postMessage("Hi from worker")
}


So the main thread creates a worker and posts a message.

Upon receiving the message, worker responds back

main thread can again catch this message using "onmessage" similar to how the worker thread reads.


Now moving the computation logic to worker file so that our main thread is not blocked and change background button works anytime

worker.js

onmesage = (message=> {
  let total = 0;
  for(let i=0i<100000000i++) {
    for(let j=0j<100j++) {
      total = total - i + j;
    }
  }
  postMessage(total)
}


main.js

calculateBtnEle.addEventListener("click", (event=> {
    const worker = new Worker("../worker.js");
    worker.postMessage("hi");
    worker.onmessage = (msg=> {
      alert("Total is: "msg.data);
    }
})











  







Comments

Popular posts from this blog

Inside the JavaScript Memory Box: Visualizing Variables, References, and Copies

React & State Management: All Concepts

React: Communication between components