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;
|