Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 44 additions & 23 deletions src/hooks/useWorker/useWorker.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { MutableRefObject, useCallback, useRef, useState } from 'react';

import { validators } from '@/utils';
Expand Down Expand Up @@ -51,19 +52,19 @@ const useWorker = <Arg, Return, Closure = never>(

safeWorkerHelper((worker) => {
// μž‘μ—…μ΄ μ™„λ£Œλœ μŠ€λ ˆλ“œλ‘œλΆ€ν„° 이벀트 μˆ˜μ‹  #1
worker.current.onmessage = (
e: MessageEvent<Return & { error?: string }>
) => {
const payload = e.data;
worker.current.onmessage(
(e: MessageEvent<Return & { error?: string }>) => {
const payload = e.data;

if (payload?.error) {
console.error(payload.error);
if (payload?.error) {
console.error(payload.error);
clearWorker();
}

setResult(payload);
clearWorker();
}

setResult(payload);
clearWorker();
};
);

// μž‘μ—…μ„ μˆ˜ν–‰ν•  μž‘μ—… μŠ€λ ˆλ“œλ‘œ 인수 전달 #2
worker.current.postMessage([args, closure]);
Expand All @@ -84,7 +85,10 @@ const useWorker = <Arg, Return, Closure = never>(

export default useWorker;

class FunctionWorker<A, R, C> extends Worker {
class FunctionWorker<A, R, C> {
worker: Worker | null = null;
workerBlob: Blob | null = null;

constructor(workerScript: WorkerScript<A, R, C>) {
if (!validators.isClient() || !window.Worker || !globalThis.Blob) {
throw new WebWorkerError("Your browser doesn't support web workers.");
Expand All @@ -99,7 +103,7 @@ class FunctionWorker<A, R, C> extends Worker {
// this === DedicatedWorkerGlobalScope
const workerFunction = (script: WorkerScript<A, R, C>) => {
// μž‘μ—… μŠ€λ ˆλ“œλ‘œ μ „λ‹¬λœ 인수 μˆ˜μ‹  #2
this.onmessage = async ({ data }: MessageEvent<[A, C]>) => {
this.onmessage(async ({ data }: MessageEvent<[A, C]>) => {
try {
// μž‘μ—… μˆ˜ν–‰
const workerResult = await script(data[0], data[1]);
Expand All @@ -109,31 +113,40 @@ class FunctionWorker<A, R, C> extends Worker {
} catch (error) {
this.postMessage({ error });
}
};
});
};

try {
const workerBlob = new Blob(
this.workerBlob = new Blob(
[`(${workerFunction.toString()})(${workerScript.toString()})`],
{ type: 'application/javascript' }
);

super(URL.createObjectURL(workerBlob));
this.worker = new Worker(URL.createObjectURL(this.workerBlob));
} catch (error) {
throw new WebWorkerError(
`Failed to create workerBlob: ${error instanceof Error ? error.message : 'unknown error'}`
);
}
}
}

const validateRef = <T>(workerRef: MutableRefObject<T | null>) => {
return (action: (arg: MutableRefObject<T>) => void) => {
if (workerRef.current) {
action(workerRef as MutableRefObject<T>);
onmessage(callback: (message: MessageEvent) => any) {
if (this.worker) {
this.worker.onmessage = callback;
}
};
};
}

postMessage(message: any): void {
if (this.worker) {
this.worker.postMessage(message);
}
}

terminate(): void {
if (this.worker) {
this.worker.terminate();
}
}
}

class WebWorkerError extends Error {
constructor(message: string) {
Expand All @@ -142,3 +155,11 @@ class WebWorkerError extends Error {
this.name = 'WebWorkerError';
}
}

const validateRef = <T>(workerRef: MutableRefObject<T | null>) => {
return (action: (arg: MutableRefObject<T>) => void) => {
if (workerRef.current) {
action(workerRef as MutableRefObject<T>);
}
};
};
Loading