1
- import { EMPTY , fromEvent , merge , Observable } from 'rxjs' ;
2
- import { take , tap } from 'rxjs/operators' ;
1
+ import { EMPTY , fromEvent , merge , Observable , Subject } from 'rxjs' ;
2
+ import { take , takeUntil , tap } from 'rxjs/operators' ;
3
3
import { WORKER_BLANK_FN } from '../consts/worker-fn-template' ;
4
4
import { TypedMessageEvent } from '../types/typed-message-event' ;
5
5
import { WorkerFunction } from '../types/worker-function' ;
6
6
7
7
export class WebWorker < T = any , R = any > extends Observable < TypedMessageEvent < R > > {
8
8
private readonly worker : Worker | undefined ;
9
9
private readonly url : string ;
10
+ private readonly destroy$ : Subject < void > ;
10
11
11
12
constructor ( url : string , options ?: WorkerOptions ) {
12
13
let worker : Worker | undefined ;
@@ -19,26 +20,29 @@ export class WebWorker<T = any, R = any> extends Observable<TypedMessageEvent<R>
19
20
}
20
21
21
22
super ( subscriber => {
23
+ let eventStream$ : Observable < TypedMessageEvent < R > | ErrorEvent > = EMPTY ;
24
+
22
25
if ( error ) {
23
26
subscriber . error ( error ) ;
27
+ } else if ( this . destroy$ . isStopped ) {
28
+ subscriber . complete ( ) ;
29
+ } else if ( worker ) {
30
+ eventStream$ = merge (
31
+ fromEvent < TypedMessageEvent < R > > ( worker , 'message' ) . pipe (
32
+ tap ( event => subscriber . next ( event ) ) ,
33
+ ) ,
34
+ fromEvent < ErrorEvent > ( worker , 'error' ) . pipe (
35
+ tap ( event => subscriber . error ( event ) ) ,
36
+ ) ,
37
+ ) . pipe ( takeUntil ( this . destroy$ ) ) ;
24
38
}
25
39
26
- const eventStream$ = worker
27
- ? merge (
28
- fromEvent < TypedMessageEvent < R > > ( worker , 'message' ) . pipe (
29
- tap ( event => subscriber . next ( event ) ) ,
30
- ) ,
31
- fromEvent < ErrorEvent > ( worker , 'error' ) . pipe (
32
- tap ( event => subscriber . error ( event ) ) ,
33
- ) ,
34
- )
35
- : EMPTY ;
36
-
37
- return eventStream$ . subscribe ( ) ;
40
+ eventStream$ . subscribe ( ) . add ( subscriber ) ;
38
41
} ) ;
39
42
40
43
this . worker = worker ;
41
44
this . url = url ;
45
+ this . destroy$ = new Subject < void > ( ) ;
42
46
}
43
47
44
48
static fromFunction < T , R > (
@@ -57,7 +61,11 @@ export class WebWorker<T = any, R = any> extends Observable<TypedMessageEvent<R>
57
61
58
62
worker . postMessage ( data ) ;
59
63
60
- return promise ;
64
+ return promise . then ( result => {
65
+ worker . terminate ( ) ;
66
+
67
+ return result ;
68
+ } ) ;
61
69
}
62
70
63
71
private static createFnUrl ( fn : WorkerFunction ) : string {
@@ -69,11 +77,18 @@ export class WebWorker<T = any, R = any> extends Observable<TypedMessageEvent<R>
69
77
}
70
78
71
79
terminate ( ) {
80
+ if ( this . destroy$ . isStopped ) {
81
+ return ;
82
+ }
83
+
72
84
if ( this . worker ) {
73
85
this . worker . terminate ( ) ;
74
86
}
75
87
76
88
URL . revokeObjectURL ( this . url ) ;
89
+
90
+ this . destroy$ . next ( ) ;
91
+ this . destroy$ . complete ( ) ;
77
92
}
78
93
79
94
postMessage ( value : T ) {
0 commit comments