-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathuse-pyodide-worker.ts
More file actions
82 lines (66 loc) · 2.1 KB
/
Copy pathuse-pyodide-worker.ts
File metadata and controls
82 lines (66 loc) · 2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { useEffect, useRef, useState } from 'react';
import { useToast } from './use-toast';
type WorkerStatus = 'idle' | 'loading' | 'ready' | 'error';
type WorkerResponse =
| { type: 'status'; payload: WorkerStatus }
| { type: 'error'; payload: string }
| { type: 'result'; payload: string };
export const usePyodideWorker = () => {
const [status, setStatus] = useState<WorkerStatus>('idle');
const workerRef = useRef<Worker>();
const { toast } = useToast();
useEffect(() => {
workerRef.current = new Worker(
new URL('../workers/pyodide.worker.ts', import.meta.url),
{
type: 'module',
}
);
workerRef.current.onmessage = (event: MessageEvent<WorkerResponse>) => {
const { type, payload } = event.data;
switch (type) {
case 'status':
setStatus(payload);
break;
case 'error':
toast({
variant: 'destructive',
title: 'Error',
description: payload,
});
setStatus('error');
break;
}
};
workerRef.current.postMessage({ type: 'init' });
return () => {
workerRef.current?.terminate();
};
}, [toast]);
const runPython = async <T>(code: string): Promise<T> => {
return new Promise((resolve, reject) => {
if (!workerRef.current || status !== 'ready') {
reject(new Error('Worker not ready'));
return;
}
const handler = (event: MessageEvent<WorkerResponse>) => {
const { type, payload } = event.data;
if (type === 'result') {
workerRef.current?.removeEventListener('message', handler);
resolve(JSON.parse(payload) as T);
} else if (type === 'error') {
workerRef.current?.removeEventListener('message', handler);
reject(new Error(payload));
}
};
workerRef.current.addEventListener('message', handler);
workerRef.current.postMessage({ type: 'run', payload: { code } });
});
};
return {
error: status === 'error',
loading: status === 'loading',
ready: status === 'ready',
runPython,
};
};