🚀 demo page workerize load

This commit is contained in:
platane
2022-03-25 10:37:49 +01:00
parent 58176f658e
commit 829a59da98
4 changed files with 109 additions and 12 deletions

View File

@@ -1,18 +1,17 @@
import { getBestRoute } from "@snk/solver/getBestRoute";
import { Color, copyGrid, Grid } from "@snk/types/grid";
import { step } from "@snk/solver/step";
import { isStableAndBound, stepSpring } from "./springUtils";
import { Res } from "@snk/github-user-contribution";
import { Snake } from "@snk/types/snake";
import type { Res } from "@snk/github-user-contribution";
import type { Snake } from "@snk/types/snake";
import {
drawLerpWorld,
getCanvasWorldSize,
Options,
} from "@snk/draw/drawWorld";
import { userContributionToGrid } from "../action/userContributionToGrid";
import { snake4 as snake } from "@snk/types/__fixtures__/snake";
import { getPathToPose } from "@snk/solver/getPathToPose";
import { userContributionToGrid } from "@snk/action/userContributionToGrid";
import { createSvg } from "@snk/svg-creator";
import { createRpcClient } from "./worker-utils";
import type { API as WorkerAPI } from "./demo.interactive.worker";
const createForm = ({
onSubmit,
@@ -47,15 +46,24 @@ const createForm = ({
form.addEventListener("submit", (event) => {
event.preventDefault();
onSubmit(input.value).catch((err) => {
label.innerText = "error :(";
throw err;
});
onSubmit(input.value)
.finally(() => {
clearTimeout(timeout);
})
.catch((err) => {
label.innerText = "error :(";
throw err;
});
input.disabled = true;
submit.disabled = true;
form.appendChild(label);
label.innerText = "loading ...";
const timeout = setTimeout(() => {
label.innerText = "loading ( it might take a while ) ... ";
}, 5000);
});
//
@@ -75,6 +83,7 @@ const createGithubProfile = () => {
container.style.opacity = "0";
container.style.display = "flex";
container.style.flexDirection = "column";
container.style.height = "120px";
container.style.alignItems = "flex-start";
const image = document.createElement("img");
image.style.width = "100px";
@@ -232,13 +241,24 @@ const onSubmit = async (userName: string) => {
};
const grid = userContributionToGrid(cells, colorScheme);
const chain = getBestRoute(grid, snake)!;
chain.push(...getPathToPose(chain.slice(-1)[0], snake)!);
const chain = await getChain(grid);
dispose();
createViewer({ grid0: grid, chain, drawOptions });
};
const worker = new Worker(
new URL(
"./demo.interactive.worker.ts",
// @ts-ignore
import.meta.url
)
);
const { getChain } = createRpcClient<WorkerAPI>(worker);
const profile = createGithubProfile();
const { dispose } = createForm({
onSubmit,

View File

@@ -0,0 +1,17 @@
import { getBestRoute } from "@snk/solver/getBestRoute";
import { getPathToPose } from "@snk/solver/getPathToPose";
import { snake4 as snake } from "@snk/types/__fixtures__/snake";
import type { Grid } from "@snk/types/grid";
import { createRpcServer } from "./worker-utils";
const getChain = (grid: Grid) => {
const chain = getBestRoute(grid, snake)!;
chain.push(...getPathToPose(chain.slice(-1)[0], snake)!);
return chain;
};
const api = { getChain };
export type API = typeof api;
createRpcServer(api);

View File

@@ -2,6 +2,7 @@
"name": "@snk/demo",
"version": "1.0.0",
"dependencies": {
"@snk/action": "1.0.0",
"@snk/draw": "1.0.0",
"@snk/github-user-contribution": "1.0.0",
"@snk/solver": "1.0.0",

View File

@@ -0,0 +1,59 @@
type API = Record<string, (...args: any[]) => any>;
const symbol = "worker-rpc__";
export const createRpcServer = (api: API) =>
self.addEventListener("message", async (event) => {
if (event.data?.symbol === symbol) {
try {
const res = await api[event.data.methodName](...event.data.args);
self.postMessage({ symbol, key: event.data.key, res });
} catch (error: any) {
postMessage({ symbol, key: event.data.key, error: error.message });
}
}
});
export const createRpcClient = <API_ extends API>(worker: Worker) => {
const originalTerminate = worker.terminate;
worker.terminate = () => {
worker.dispatchEvent(new Event("terminate"));
originalTerminate.call(worker);
};
return new Proxy(
{} as {
[K in keyof API_]: (
...args: Parameters<API_[K]>
) => Promise<Awaited<ReturnType<API_[K]>>>;
},
{
get:
(_, methodName) =>
(...args: any[]) =>
new Promise((resolve, reject) => {
const key = Math.random().toString();
const onTerminate = () => {
worker.removeEventListener("terminate", onTerminate);
worker.removeEventListener("message", onMessageHandler);
reject(new Error("worker terminated"));
};
const onMessageHandler = (event: MessageEvent) => {
if (event.data?.symbol === symbol && event.data.key === key) {
if (event.data.error) reject(event.data.error);
else if (event.data.res) resolve(event.data.res);
worker.removeEventListener("terminate", onTerminate);
worker.removeEventListener("message", onMessageHandler);
}
};
worker.addEventListener("message", onMessageHandler);
worker.addEventListener("terminate", onTerminate);
worker.postMessage({ symbol, key, methodName, args });
}),
}
);
};