86 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			86 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | function createPseudoWorker(context) { | ||
|  |   class PseudoWorker { | ||
|  |     constructor(path) { | ||
|  |       this.terminated = false; | ||
|  |       this.worker = context.evaluateHandle(path => new Worker(path), path); | ||
|  |       this.listenToWorker('onmessage'); | ||
|  |       this.listenToWorker('onerror'); | ||
|  |     } | ||
|  | 
 | ||
|  |     terminate() { | ||
|  |       this.terminated = true; | ||
|  |       this.worker.then(worker => | ||
|  |         context.evaluate(worker => worker.terminate(), worker) | ||
|  |       ); | ||
|  |     } | ||
|  | 
 | ||
|  |     listenToWorker(eventName) { | ||
|  |       this.worker.then(async worker => { | ||
|  |         const producer = await context.evaluateHandle( | ||
|  |           (worker, eventName) => { | ||
|  |             let callback; | ||
|  |             const queue = []; | ||
|  |             function send(event) { | ||
|  |               if (!queue.length && callback) { | ||
|  |                 callback(); | ||
|  |               } | ||
|  |               queue.push(event); | ||
|  |             } | ||
|  | 
 | ||
|  |             worker[eventName] = e => send(e); | ||
|  | 
 | ||
|  |             const resolver = resolve => (callback = resolve); | ||
|  |             async function* produce() { | ||
|  |               while (true) { | ||
|  |                 while (queue.length) { | ||
|  |                   yield queue.shift(); | ||
|  |                 } | ||
|  |                 await new Promise(resolver); | ||
|  |               } | ||
|  |             } | ||
|  |             return produce(); | ||
|  |           }, | ||
|  |           worker, | ||
|  |           eventName | ||
|  |         ); | ||
|  |         while (!this.terminated) { | ||
|  |           try { | ||
|  |             const data = await context.evaluate( | ||
|  |               producer => | ||
|  |                 producer | ||
|  |                   .next() | ||
|  |                   .then(({ value: { data, message } }) => ({ data, message })), | ||
|  |               producer | ||
|  |             ); | ||
|  |             if (this[eventName]) { | ||
|  |               this[eventName](data); | ||
|  |             } | ||
|  |           } catch (err) { | ||
|  |             break; | ||
|  |           } | ||
|  |         } | ||
|  |       }); | ||
|  |     } | ||
|  | 
 | ||
|  |     async postMessage(msg) { | ||
|  |       if (this.terminated) { | ||
|  |         throw new Error('Worker is terminated.'); | ||
|  |       } | ||
|  |       try { | ||
|  |         await this.worker.then(worker => | ||
|  |           worker | ||
|  |             .executionContext() | ||
|  |             .evaluate((worker, msg) => worker.postMessage(msg), worker, msg) | ||
|  |         ); | ||
|  |       } catch (e) { | ||
|  |         if (this.onerror) { | ||
|  |           this.onerror({ message: e.message }); | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |   return PseudoWorker; | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = createPseudoWorker; |