JS Web Workers can make your web app more responsive in many cases. JS is single thread, so when JS is running you can’t update the DOM and your page is basically frozen. This is not an issue if you are running a small bit of code, or your code runs in small bursts and returns control back to your browser every so often. But sometimes long calculations are required and you don’t want your web app to choke.
Web Workers can run JS in a separate thread from your browser allowing it to be responsive while your JS code crunches it’s numbers. Basically you create a Web Worker, just JS code that will run alongside your web page thread. To start the Web Worker code you must send a
webworker.postMessage(dataIn)
to the Web Worker where it is received from it’s
onmessage = function(event) { var input = event.data; }
function.
When your Web Worker code wants to pass data back to your web page, it also uses:
postMessage(returnThisData);
and your web page accepts it using:
webworker.onmessage = function (event) { let recievedData = event.data; };
See: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
Normally your Web Worker code is in a separate file from your web page code.
const myWorker = new Worker("worker.js");
Note that the worker.js file must be on the same domain. It can’t be accessed from another web server.
There are some cases where you might want, or require, your Web Worker code to be in the same file that your calling code is in. For me, that case was codepen.
So how can we do that? There are two ways that I have seen. Both convert JS text into a BLOB then we create a local URL for that blob. Then we just feed that URL to “new Worker(thatURL)”
See: https://www.geeksforgeeks.org/javascript/javascript-blob
Both examples are explained here: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#embedded_workers
In my first example, our Web Worker text will be in our HTML page. type=”text/js-worker” is a MUST. If you use type=”text/javascript” your browser will run the code right away. We don’t want the code to run in the browser thread.
<script id="webworker" type="text/js-worker">
onmessage = function(event) {
var input = event.data;
Start_Worker(input);
};
function Start_Worker(input) {
let divisions = input.divisions;
...
postMessage(pi);
}
</script>
Now to create and start the webworker.
//get inline webworker code and put it in a Blob
let inline_webworker_blob = new Blob(
[document.querySelector("#webworker").textContent],
{ type: "text/javascript" }
);
//create the webworker from the Blob URL
webworker = new Worker(window.URL.createObjectURL(inline_webworker_blob));
//start the web worker with input data we are sending to it
webworker.postMessage(input);
The second method will allow us to create a Web Worker from a single function. Within that function will be other nested functions. The outer function will not be used or called in the Web Worker. Just the nested functions.
//this will be the web worker code
function function_containing_webworker(){
onmessage = function(event) {
var input = event.data;
Start_Worker(input);
};
function Start_Worker(input) {
let divisions = input.divisions;
...
postMessage(pi);
}
//this converts the function to a blob and also returns the local blob URL
function fn2workerURL(fn) {
const blob = new Blob([`(${fn.toString()})()`], { type: "text/javascript" });
return URL.createObjectURL(blob);
}
//create blob and get the local Blob URL
let webworkerurl = fn2workerURL(function_containing_webworker);
//create the web worker
var webworker = new Worker(webworkerurl);
Example at: https://github.com/vpelss/Monte-Carlo-Pi
