Skip to content

Instantly share code, notes, and snippets.

@ststeiger
Last active August 20, 2024 16:19
Show Gist options
  • Save ststeiger/ef3f3152e9abe1fb81f73dd0c0f7d623 to your computer and use it in GitHub Desktop.
Save ststeiger/ef3f3152e9abe1fb81f73dd0c0f7d623 to your computer and use it in GitHub Desktop.
Awaiting a worker request in JS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<title>Awaiting Worker Request</title>
<style>
.loader
{
width: 30px;
aspect-ratio: 4;
--_g: no-repeat radial-gradient(circle closest-side,#000 90%,#0000);
background: var(--_g) 0% 50%, var(--_g) 50% 50%, var(--_g) 100% 50%;
background-size: calc(100%/3) 100%;
animation: l7 1s infinite linear;
}
@keyframes l7
{
33%
{
background-size: calc(100%/3) 0%,calc(100%/3) 100%,calc(100%/3) 100%
}
50%
{
background-size: calc(100%/3) 100%,calc(100%/3) 0%,calc(100%/3) 100%
}
66%
{
background-size: calc(100%/3) 100%,calc(100%/3) 100%,calc(100%/3) 0%
}
}
</style>
</head>
<body>
<h1>Whitespace Removal Benchmark</h1>
<div id="result">
<div class="loader" style="display: inline-block;"></div>
<div style="display: inline-block; font-size: 5mm;" class="loading">Benchmark running&nbsp;</div>
<div class="loader" style="display: inline-block;"></div>
</div>
<!--
https://css-loaders.com/dots/
-->
<script>
const workerCode = `"use strict";
function cryptoRand()
{
const randomBuffer = new Uint32Array(1);
(crypto || msCrypto).getRandomValues(randomBuffer);
return ( randomBuffer[0] / (0xffffffff + 1) );
}
function getRandomInt(min, max)
{
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(cryptoRand() * (max - min + 1)) + min;
}
function sleep(interval)
{
return new Promise(
function (resolve, reject)
{
let wait = setTimeout(
function ()
{
clearTimeout(wait);
if(getRandomInt(1,2) % 2 == 0)
resolve();
else
reject(new Error("Promise timed out ! "));
}
, interval
);
});
}
async function processData(data)
{
let interval = getRandomInt(1000, 5000);
await sleep(interval);
return data;
}
async function handleSomeTask(id, data)
{
try
{
// Process the data
const result = await processData(data);
// throw new Error("hello");
self.postMessage({ "id": id, "err":null, "result": result });
}
catch (err)
{
self.postMessage({ "id": id, "err":err, "result": null });
}
}
self.onmessage = function(event)
{
const { id, data } = event.data;
handleSomeTask(id, data);
};
`;
const blob = new Blob([workerCode], { type: 'text/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
worker.onmessage = function(event)
{
const { id, err, result } = event.data;
// console.log("received", event.data);
if (err != null)
{
const reject = worker.workerErrorCallbacks.get(id);
if (reject)
{
reject(err);
worker.workerSuccessCallbacks.delete(id);
worker.workerErrorCallbacks.delete(id);
}
}
else
{
const resolve = worker.workerSuccessCallbacks.get(id);
if (resolve)
{
resolve(result);
worker.workerSuccessCallbacks.delete(id);
worker.workerErrorCallbacks.delete(id);
}
}
};
function generateRandom32BitInteger()
{
var array = new Int8Array(4);
(window.crypto || window.msCrypto).getRandomValues(array);
var dataView = new DataView(array.buffer);
var uint = dataView.getUint32();
// var f = uint / (0xffffffff + 1); // 0xFFFFFFFF = uint32.MaxValue (+1 because Math.random is inclusive of 0, but not 1)
// return f;
return uint;
}
function generateRandom128BitInteger()
{
const array = new Uint8Array(16);
crypto.getRandomValues(array);
let value = 0n;
for (let i = 0; i < array.length; i++)
{
value = (value << 8n) + BigInt(array[i]);
}
return value;
}
function generateRandomUuid()
{
const array = new Uint8Array(16);
crypto.getRandomValues(array);
let value = 0n;
for (let i = 0; i < array.length; i++)
{
value = (value << 8n) + BigInt(array[i]);
}
// return value;
const hexString = value.toString(16).padStart(32, '0');
// Format the hex string into UUID format
const uuid = `${hexString.slice(0, 8)}-${hexString.slice(8, 12)}-${hexString.slice(12, 16)}-${hexString.slice(16, 20)}-${hexString.slice(20)}`;
return uuid;
}
async function callWorkerFunction(worker, data)
{
if (!worker.workerSuccessCallbacks)
{
worker.workerSuccessCallbacks = new Map();
worker.workerErrorCallbacks = new Map();
// worker.callbackId = 0;;
}
// const id = Math.random(); // Generate a unique identifier
// const id = generateRandomUuid();
// const id = generateRandom128BitInteger();
const id = generateRandom32BitInteger();
// const id = worker.callbackId++;
return new Promise(
function (resolve, reject)
{
// worker.onmessage = function(event)
// {
// console.log("received event", event.data);
// if (event.data.id === id)
// {
// resolve(event.data.result);
// // worker.terminate(); // Optional: Terminate the worker after the result
// }
// };
worker.workerSuccessCallbacks.set(id, resolve);
worker.workerErrorCallbacks.set(id, reject);
worker.postMessage({ id, data });
}
);
}
function generateRandomString(min, max)
{
const length = Math.floor(Math.random() * (max - min + 1)) + min;
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
let result = [];
for (let i = 0; i < length; i++)
{
result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));
}
return result.join("");
}
async function testCall()
{
try
{
const randomString = generateRandomString(5, 15);
let passedData = { "hello": "kitty", "foo": "bar", "something": randomString };
const result = await callWorkerFunction(worker, passedData);
console.log("result for " + randomString + ":", result);
}
catch (err)
{
console.log("failed:", err);
}
}
function test()
{
for (let i = 0; i < 20; ++i)
{
testCall();
}
}
test();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment