Reintroducing WebWorkers (pfeeew, Vite makes it tough !)
This commit is contained in:
1 parent
02f02984e5
commit
5de30283b1
52 files changed
+3362
-47
No files matched your search
@@ -0,0 +1,37 @@
|
||||
import dispatch, { init, worker } from './dispatcher-main';
|
||||
|
||||
jest.mock('./get-worker', () => ({
|
||||
getWorker: () => ({
|
||||
port: {
|
||||
postMessage: jest.fn(),
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('The dispatcher-main', () => {
|
||||
beforeEach(() => {
|
||||
init();
|
||||
});
|
||||
test('should create a new shared web worker', () => {
|
||||
expect(worker).toBeDefined();
|
||||
});
|
||||
test('should create a onmessage function', () => {
|
||||
expect(worker.port.onmessage).toBeDefined();
|
||||
});
|
||||
test('should return a promise if no callback is provided', () => {
|
||||
expect(dispatch('ping')).toBeInstanceOf(Promise);
|
||||
});
|
||||
test('should forward the message', () => {
|
||||
dispatch('ping');
|
||||
expect(worker.port.postMessage).toBeCalledWith({ id: 0, payload: 'ping' });
|
||||
});
|
||||
test('should return the response', () => {
|
||||
var response;
|
||||
const callback = (error, success) => {
|
||||
response = success;
|
||||
};
|
||||
dispatch('ping', callback);
|
||||
worker.port.onmessage({ data: { id: 0, payload: 'pong' } });
|
||||
expect(response).toEqual('pong');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
import { getWorker } from './get-worker';
|
||||
|
||||
declare global {
|
||||
var dispatcherQueue: { index: number; queue: Map<number, any> };
|
||||
}
|
||||
|
||||
export var worker: any;
|
||||
|
||||
export const init = () => {
|
||||
console.log({ caller: 'dispatcher-main / init' });
|
||||
globalThis.dispatcherQueue = { index: 0, queue: new Map() };
|
||||
console.log({ caller: 'dispatcher-main / init', globalThis });
|
||||
|
||||
worker = getWorker();
|
||||
console.log({ caller: 'dispatcher-main / init', worker });
|
||||
|
||||
worker.onmessage = (event: any) => {
|
||||
const { id, payload } = event.data;
|
||||
dispatcherQueue.queue.get(id)(null, payload);
|
||||
dispatcherQueue.queue.delete(id);
|
||||
};
|
||||
};
|
||||
|
||||
const dispatch = (
|
||||
payload: any,
|
||||
callBack?: (error: any, result: any) => void
|
||||
) => {
|
||||
if (worker === undefined) {
|
||||
init();
|
||||
}
|
||||
if (callBack === undefined) {
|
||||
/** If a callback function is not provided, return a promise */
|
||||
return new Promise((resolve, reject) => {
|
||||
dispatch(payload, (error, result) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
/** Otherwise, use the callback function */
|
||||
dispatcherQueue.queue.set(dispatcherQueue.index, callBack);
|
||||
const message = {
|
||||
id: dispatcherQueue.index++,
|
||||
payload: payload,
|
||||
};
|
||||
worker.postMessage(message);
|
||||
console.log({ caller: 'dispatcher-main / dispatch', message });
|
||||
};
|
||||
|
||||
export default dispatch;
|
||||
@@ -0,0 +1,33 @@
|
||||
import worker from './dispatcher-worker';
|
||||
|
||||
jest.mock('../db', () => ({
|
||||
initDb: () => 'called initDb',
|
||||
}));
|
||||
|
||||
describe('The dispatcher-worker ', () => {
|
||||
let port;
|
||||
beforeEach(() => {
|
||||
port = {
|
||||
postMessage: jest.fn(),
|
||||
};
|
||||
worker.onconnect({ ports: [port] });
|
||||
});
|
||||
test('creates a onmessage function', () => {
|
||||
expect(port.onmessage).toBeDefined();
|
||||
expect(port.postMessage).not.toBeCalled();
|
||||
});
|
||||
test('receives a ping and sends back an unknownAction', async () => {
|
||||
await port.onmessage({ data: { id: 5, payload: { action: 'ping' } } });
|
||||
expect(port.postMessage).toBeCalledWith({
|
||||
id: 5,
|
||||
payload: 'unknownAction',
|
||||
});
|
||||
});
|
||||
test('calls initDb when required', async () => {
|
||||
await port.onmessage({ data: { id: 5, payload: { action: 'initDb' } } });
|
||||
expect(port.postMessage).toBeCalledWith({
|
||||
id: 5,
|
||||
payload: 'called initDb',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
/// <reference lib="webworker" />
|
||||
import { initDb } from '../db';
|
||||
import {
|
||||
putNewGpx,
|
||||
existsGpx,
|
||||
pruneAndSaveImportedGpx,
|
||||
getGpxesForViewport,
|
||||
getGpx,
|
||||
} from '../db/gpx';
|
||||
import { getTrk, putNewTrk } from '../db/trk';
|
||||
import { getTrkseg } from '../db/trkseg';
|
||||
|
||||
const self = globalThis as unknown as WorkerGlobalScope;
|
||||
|
||||
const actions = {
|
||||
initDb,
|
||||
putNewGpx,
|
||||
putNewTrk,
|
||||
existsGpx,
|
||||
pruneAndSaveImportedGpx,
|
||||
getGpxesForViewport,
|
||||
getGpx,
|
||||
getTrk,
|
||||
getTrkseg,
|
||||
};
|
||||
|
||||
console.log({ caller: 'dispatcher-worker', actions });
|
||||
|
||||
onmessage = async function (e) {
|
||||
console.log({ caller: 'dispatcher-worker / onmessage', e });
|
||||
const { id, payload } = e.data;
|
||||
console.log(`payload.action in actions: ${payload.action in actions}`);
|
||||
var returnValue: any = 'unknownAction';
|
||||
if (payload.action in actions) {
|
||||
returnValue = await actions[<keyof typeof actions>payload.action](
|
||||
payload.params
|
||||
);
|
||||
}
|
||||
postMessage({ id: id, payload: returnValue });
|
||||
};
|
||||
|
||||
//export default self;
|
||||
@@ -0,0 +1,8 @@
|
||||
export const getWorker = () => {
|
||||
console.log({ caller: 'getWorker' });
|
||||
return new Worker(new URL('./dispatcher-worker', import.meta.url), {
|
||||
type: 'module',
|
||||
});
|
||||
};
|
||||
|
||||
export default getWorker;
|
||||
Reference in new issue
Block a user