-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathuntilDestroy.ts
47 lines (43 loc) · 1.64 KB
/
untilDestroy.ts
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
import { Observable } from 'rxjs/Observable';
import { takeUntil } from 'rxjs/operators';
// create a symbol identify the observable I add to
// the component so it doesn't conflict with anything.
// I need this so I'm able to add the desired behaviour to the component.
export const destroy$ = Symbol('destroy$');
/**
* an operator that takes until destroy it takes a components this a parameter
* returns a lettable RxJS operator.
*/
export const untilDestroy = component => <T>(source: Observable<T>) => {
if (component[destroy$] === undefined) {
// only hookup each component once.
addDestroyObservableToComponent(component);
}
// pipe in the takeuntil destroy$ and return the source unaltered
return source.pipe(takeUntil(component[destroy$]));
};
export function addDestroyObservableToComponent(component) {
component[destroy$] = new Observable<void>(observer => {
// keep track of the original destroy function,
// the user might do something in there
const orignalDestroy = component.ngOnDestroy;
if (orignalDestroy === undefined) {
// Angular does not support dynamic added destroy methods
// so make sure there is one.
throw new Error(
'untilDestroy operator needs the component to have an ngOnDestroy method'
);
}
// replace the ngOndestroy
component.ngOnDestroy = () => {
// fire off the destroy observable
observer.next();
// complete the observable
observer.complete();
// and at last, call the original destroy
orignalDestroy.call(component);
};
// return cleanup function.
return _ => (component[destroy$] = undefined);
});
}