|
1 | | -import { useEffect, useRef, useState } from 'react'; |
| 1 | +import { useCallback, useEffect, useState } from 'react'; |
2 | 2 | import Smelter from '../smelter/live'; |
3 | 3 | import type { SmelterInstanceOptions } from '../manager'; |
4 | 4 |
|
5 | 5 | export function useSmelter(options: SmelterInstanceOptions): Smelter | undefined { |
6 | 6 | const [smelter, setSmelter] = useState<Smelter>(); |
7 | | - const prevSmelter = useRef<Smelter>(); |
| 7 | + const [promiseQueue, setPromiseQueue] = useState<(() => Promise<void>)[]>([]); |
| 8 | + const [isWaiting, setIsWaiting] = useState(false); |
| 9 | + |
| 10 | + const enqueue = useCallback((fn: () => Promise<void>) => { |
| 11 | + setPromiseQueue(queue => [ |
| 12 | + ...queue, |
| 13 | + fn, |
| 14 | + ]) |
| 15 | + }, []); |
8 | 16 |
|
9 | 17 | useEffect(() => { |
10 | 18 | const smelter = new Smelter(options); |
11 | | - const smelterToTerminate = prevSmelter.current; |
12 | | - prevSmelter.current = smelter; |
13 | 19 |
|
14 | 20 | let cancel = false; |
15 | | - (async () => { |
16 | | - if (smelterToTerminate) { |
17 | | - console.log("Terminate"); |
18 | | - } |
19 | | - await smelterToTerminate?.terminate().catch(() => { }); |
20 | | - console.log("Init"); |
| 21 | + enqueue(async () => { |
21 | 22 | await smelter.init(); |
22 | 23 | await smelter.start(); |
23 | 24 | if (!cancel) { |
24 | 25 | setSmelter(smelter); |
25 | 26 | } |
26 | | - })(); |
| 27 | + }); |
27 | 28 |
|
28 | 29 | return () => { |
29 | 30 | cancel = true; |
| 31 | + enqueue(async () => await smelter.terminate()); |
30 | 32 | }; |
31 | | - }, [options?.url]); |
| 33 | + }, [options?.url, enqueue]); |
32 | 34 |
|
33 | 35 | useEffect(() => { |
34 | | - return () => { |
35 | | - if (prevSmelter.current) { |
36 | | - console.log("Terminate unmount"); |
37 | | - } |
38 | | - // It runs only during unmount |
39 | | - void prevSmelter.current?.terminate().catch(() => { }); |
| 36 | + if (isWaiting) { |
| 37 | + return; |
| 38 | + } |
| 39 | + setIsWaiting(true); |
| 40 | + |
| 41 | + const fn = promiseQueue[0]; |
| 42 | + if (fn) { |
| 43 | + void (async () => { |
| 44 | + await fn(); |
| 45 | + setPromiseQueue(promiseQueue.slice(1)); |
| 46 | + setIsWaiting(false); |
| 47 | + })(); |
40 | 48 | } |
41 | | - }, []) |
| 49 | + }, [promiseQueue, isWaiting]); |
42 | 50 |
|
43 | 51 | return smelter; |
44 | 52 | } |
0 commit comments