-
Notifications
You must be signed in to change notification settings - Fork 98
/
until-destroy.ts
77 lines (65 loc) 路 2.1 KB
/
until-destroy.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
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
import {
InjectableType,
傻ComponentType as ComponentType,
傻DirectiveType as DirectiveType
} from '@angular/core';
import { SubscriptionLike } from 'rxjs';
import { PipeType, isPipe } from './ivy';
import {
getSymbol,
isFunction,
UntilDestroyOptions,
completeSubjectOnTheInstance,
markAsDecorated
} from './internals';
function unsubscribe(property: SubscriptionLike | undefined): void {
property && isFunction(property.unsubscribe) && property.unsubscribe();
}
function unsubscribeIfPropertyIsArrayLike(property: any[]): void {
Array.isArray(property) && property.forEach(unsubscribe);
}
function decorateNgOnDestroy(
ngOnDestroy: (() => void) | null | undefined,
options: UntilDestroyOptions
) {
return function(this: any) {
// Invoke the original `ngOnDestroy` if it exists
ngOnDestroy && ngOnDestroy.call(this);
// It's important to use `this` instead of caching instance
// that may lead to memory leaks
completeSubjectOnTheInstance(this, getSymbol());
// Check if subscriptions are pushed to some array
if (options.arrayName) {
return unsubscribeIfPropertyIsArrayLike(this[options.arrayName]);
}
// Loop through the properties and find subscriptions
if (options.checkProperties) {
for (const property in this) {
if (options.blackList?.includes(property)) {
continue;
}
unsubscribe(this[property]);
}
}
};
}
function decorateProviderDirectiveOrComponent<T>(
type: InjectableType<T> | DirectiveType<T> | ComponentType<T>,
options: UntilDestroyOptions
): void {
type.prototype.ngOnDestroy = decorateNgOnDestroy(type.prototype.ngOnDestroy, options);
}
function decoratePipe<T>(type: PipeType<T>, options: UntilDestroyOptions): void {
const def = type.傻pipe;
def.onDestroy = decorateNgOnDestroy(def.onDestroy, options);
}
export function UntilDestroy(options: UntilDestroyOptions = {}): ClassDecorator {
return (type: any) => {
if (isPipe(type)) {
decoratePipe(type, options);
} else {
decorateProviderDirectiveOrComponent(type, options);
}
markAsDecorated(type);
};
}