Web workers work in a separate thread and does not block the main thread
<!doctype html>
<html>
<head><title> web 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=0; i<100000000; i++) {
for(let j=0; j<100; j++) {
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=0; i<100000000; i++) {
for(let j=0; j<100; j++) {
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
Post a Comment