Last active
February 6, 2023 22:51
-
-
Save sketchpunk/9584e5fb82185691602cd3ea9b57f874 to your computer and use it in GitHub Desktop.
Various Web Worker Wrappers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
const fnWorker = ( evt )=>{ | |
const data = evt.data; | |
fnCreateVert( data ); | |
}; | |
async function fnCreateVert( y ){ | |
const vert = new Float32Array( [0,y,0] ); | |
console.log( 'Elevation Request', y, vert ); | |
console.log( 'Size before post', vert.byteLength ); | |
//postMessage( vert ); // Copy to main thread | |
postMessage( vert, [ vert.buffer ] ); // Transfer to main thread | |
console.log( 'Size after post', vert.byteLength ); | |
}; | |
const dw = new DynamicWorker( [fnCreateVert, fnWorker] ); | |
dw.on(( e )=>{ | |
console.log( 'Drawing Vert', Array.from( e.data ) ); | |
Ref.pnt.add( e.data, 0x00ff00, 5 ); | |
}); | |
dw.post( 1.2 ); | |
*/ | |
class DynamicWorker{ | |
constructor( fn ){ | |
if( !window.Worker ){ console.error( 'Browser does not support Web Workers' ); return; } | |
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
// Build Source | |
let src = ''; | |
if( Array.isArray( fn ) ){ | |
// Turn all the other functions into strings | |
const li = fn.length - 1; | |
for( let i=0; i < li; i++ ) src += fn[ i ].toString() + '\n'; | |
// Last function is the onMessage Handler | |
src += 'self.onmessage=' + fn[ li ].toString(); | |
}else{ | |
src = 'self.onmessage=' + fn.toString(); | |
} | |
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
// Compile source & create workier | |
const blob = new Blob( [ src ], { type:'text/javascript' } ); | |
const url = window.URL.createObjectURL( blob ); | |
window.URL.revokeObjectURL(blob); | |
//console.log( src ); | |
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
this._worker = new Worker( url, { type: 'module' } ); | |
} | |
dispose(){ this._worker.terminate(); } | |
post( data ){ this._worker.postMessage( data ); return this; } | |
once( fn ){ this._worker.addEventListener( 'message', fn, { once:true } ); return this; } | |
on( fn ){ this._worker.addEventListener( 'message', fn ); return this; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
let pworker = new PromiseWorker( v=>{ | |
console.log( "Inside ", v ); | |
return "Got " + v; | |
} ); | |
pworker.post( "test" ).then( v=>console.log( "then", v ) ); | |
*/ | |
class PromiseWorker{ | |
constructor( fn ){ | |
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
const blob = new Blob( | |
[`self.onmessage = (e)=>{ | |
const rtn = __WORKER_FN__( e.data.value ); | |
if( rtn != undefined ) self.postMessage( { id:e.data.id, value:rtn } ); | |
}; `, 'const __WORKER_FN__=', fn.toString() ], | |
{ type:'text/javascript' } | |
); | |
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
const url = window.URL.createObjectURL( blob ); | |
window.URL.revokeObjectURL( blob ); | |
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
this._promises = new Map(); | |
this._worker = new Worker( url ); | |
this._worker.addEventListener( "message", this._onMsg.bind( this ) ); | |
} | |
_onMsg( e ){ | |
const p = this._promises.get( e.data.id ); | |
if( p ){ | |
this._promises.delete( e.data.id ); | |
p.resolve( e.data.value ); | |
}else{ | |
console.warn( 'Worker Promise ID not found in map' ); | |
} | |
} | |
_nanoId( t=21 ){ | |
const r = crypto.getRandomValues( new Uint8Array( t ) ); | |
let n, e = ""; | |
for( ;t--; ){ | |
n = 63 & r[ t ]; | |
e += ( n < 36 )? n.toString(36) : | |
( n < 62 )? ( n - 26 ).toString( 36 ).toUpperCase() : | |
( n < 63 )? "_" : "-"; | |
} | |
return e; | |
} | |
post( value, fnThen=null ){ | |
const id = this._nanoId( 8 ); | |
const p = new Promise(( resolve, reject )=>{ | |
this._promises.set( id, {resolve,reject} ); | |
this._worker.postMessage( { id, value } ); | |
}); | |
return ( fnThen )? p.then( fnThen ) : p; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
let runner = new TaskRunner(); | |
runner.add( "BasicTask", BasicTask, e=>console.log( "Msg", e.data ) ); | |
runner.post( "BasicTask", "woot" ); | |
*/ | |
class BasicTask{ | |
run( e ){ | |
console.log( "Run", e.data ); | |
self.postMessage( e.data ); | |
} | |
} | |
class TaskRunner{ | |
_workers = new Map(); | |
constructor(){} | |
_newWorker( src ){ | |
const blob = new Blob( [ src ], { type:'text/javascript' } ); | |
const url = window.URL.createObjectURL( blob ); | |
window.URL.revokeObjectURL(blob); | |
return new Worker( url ); | |
} | |
add( name, task, onMsg=null ){ | |
let src = task.toString() + ` | |
const TASK = new ${task.name}(); | |
self.onmessage = e=>TASK.run( e );`; | |
let worker = this._newWorker( src ); | |
if( onMsg ) worker.addEventListener( "message", onMsg ); | |
this._workers.set( name, worker ); | |
return this; | |
} | |
on( name, fn ){ | |
const task = this._workers.get( name ); | |
if( task ) task.addEventListener( "message", fn ); | |
return this; | |
} | |
once( name, fn ){ | |
const task = this._workers.get( name ); | |
if( task ) task.addEventListener( "message", fn, { once:true } ); | |
return this; | |
} | |
post( name, data ){ | |
const task = this._workers.get( name ); | |
if( task ) task.postMessage( data ); | |
return this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment