Skip to content

Instantly share code, notes, and snippets.

@fercarvo
Last active February 21, 2024 11:55
Show Gist options
  • Save fercarvo/253762281445b85ac8586d7ded537559 to your computer and use it in GitHub Desktop.
Save fercarvo/253762281445b85ac8586d7ded537559 to your computer and use it in GitHub Desktop.
A generic javascript fileless WebWorker that can execute functions, you can pass a function to be executed outside the main thread
/**
* GenericWebWorker v2.3
*
* A Generic Javascript WebWorker that allows the user to execute and pass functions
* Is Fileless, for what the user does not need a file.js to request
*
* @author, Edgar Fernando Carvajal Ulloa <[email protected]>, <[email protected]>
* {@link https://github.com/fercarvo/GenericWebWorker}
*/
class GenericWebWorker {
/**
* @param {any} data, Any kind of arguments that will be used in the callback, functions too
*/
constructor(...data) {
this.args = data.map(a => (typeof a === 'function') ? {type:'fn', fn:a.toString()} : a)
}
//@param {function} cb, To be executed, the params must be the same number of passed in the constructor
async exec(cb) {
if (typeof cb !== 'function')
throw new Error(`${cb} not a function`);
var wk_string = this.worker.toString();
wk_string = wk_string.substring(wk_string.indexOf('{') + 1, wk_string.lastIndexOf('}'));
var wk_link = window.URL.createObjectURL( new Blob([ wk_string ]) );
var wk = new Worker( wk_link );
try {
wk.postMessage({ callback: cb.toString(), args: this.args });
var res = await new Promise((next, error) => {
wk.onmessage = e => (e.data && e.data.error) ? error(e.data.error) : next(e.data);
wk.onerror = e => error(e.message);
});
return res
} catch (e) { throw e } finally { wk.terminate(); window.URL.revokeObjectURL(wk_link) }
}
//@param {function} cb, To be executed, the 1st argument is each element of the array
async parallel(arr, cb) {
var res = [...arr].map(it => new GenericWebWorker(it, ...this.args).exec(cb))
return await Promise.all(res)
}
worker() {
onmessage = async function (e) {
try {
var cb = new Function(`return ${e.data.callback}`)();
var args = e.data.args.map(p => (p.type === 'fn') ? new Function(`return ${p.fn}`)() : p);
try {
var result = await cb(...args);//If it is a promise or async function
return postMessage(result)
} catch (e) { throw `CallbackError: ${e}` }
} catch (e) { postMessage({error: e.message}) }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment