@badisi/ngx-safe-subscribe 3.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -31
- package/esm2020/ngx-safe-subscribe.mjs +23 -16
- package/fesm2015/badisi-ngx-safe-subscribe.mjs +24 -16
- package/fesm2015/badisi-ngx-safe-subscribe.mjs.map +1 -1
- package/fesm2020/badisi-ngx-safe-subscribe.mjs +23 -16
- package/fesm2020/badisi-ngx-safe-subscribe.mjs.map +1 -1
- package/ngx-safe-subscribe.d.ts +3 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Automatically unsubscribe from RxJS observables in Angular components.
|
|
4
4
|
|
|
5
|
-
[]
|
|
6
|
-
[][npm]
|
|
6
|
+
[][npm-dl]
|
|
7
|
+
[][license]
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
[][ci-tests]
|
|
10
|
+
[][pullrequest]
|
|
10
11
|
|
|
11
12
|
:zap: *Angular <= 13 version available [here](https://github.com/Badisi/ngx-safe-subscribe/releases/tag/2.2.9)*
|
|
12
13
|
|
|
@@ -27,49 +28,68 @@ yarn add @badisi/ngx-safe-subscribe
|
|
|
27
28
|
|
|
28
29
|
SafeSubscribe is an augmentation method of Observable.
|
|
29
30
|
|
|
30
|
-
Calling
|
|
31
|
+
Calling `safeSubscribe` instead of `subscribe` will automatically unsubscribe your observable at component destroy.
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
:warning: At least a noop **ngOnDestroy** is required - but type checking will make sure you never forget about it :wink:
|
|
35
|
-
|
|
36
|
-
---------------------------------------
|
|
37
|
-
|
|
38
|
-
### safeSubscribe(target: any, next: Function, error: Function, complete: Function): Subscription
|
|
39
|
-
|
|
40
|
-
__Arguments__
|
|
41
|
-
|
|
42
|
-
* `target` - A reference to the object that is holding the observable.
|
|
43
|
-
* `next` - A handler for each delivered value. Called zero or more times after execution starts.
|
|
44
|
-
* `error` - A handler for an error notification. An error halts execution of the observable instance.
|
|
45
|
-
* `complete` - A handler for the execution-complete notification. Delayed values can continue to be delivered to the next handler after execution is complete.
|
|
46
|
-
|
|
47
|
-
__Return__
|
|
48
|
-
|
|
49
|
-
* A `Subscription` object.
|
|
50
|
-
|
|
51
|
-
__Example__
|
|
33
|
+
#### Example with Angular components
|
|
52
34
|
|
|
53
35
|
```ts
|
|
54
|
-
import { Component, OnInit
|
|
55
|
-
import {
|
|
56
|
-
import '
|
|
36
|
+
import { Component, OnInit } from '@angular/core';
|
|
37
|
+
import { SafeSubscribe } from '@badisi/ngx-safe-subscribe';
|
|
38
|
+
import { interval } from 'rxjs';
|
|
57
39
|
|
|
40
|
+
@SafeSubscribe()
|
|
58
41
|
@Component({
|
|
59
42
|
selector: 'app-component'
|
|
60
43
|
})
|
|
61
|
-
export class AppComponent implements OnInit
|
|
44
|
+
export class AppComponent implements OnInit {
|
|
62
45
|
ngOnInit() {
|
|
63
46
|
interval(1000).safeSubscribe(this, () => {
|
|
64
47
|
console.log('This log will stop on component destroy.')
|
|
65
48
|
});
|
|
66
49
|
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### Example with simple class objects
|
|
67
54
|
|
|
68
|
-
|
|
69
|
-
|
|
55
|
+
```ts
|
|
56
|
+
import { SafeSubscribe } from '@badisi/ngx-safe-subscribe';
|
|
57
|
+
import { interval } from 'rxjs';
|
|
58
|
+
|
|
59
|
+
@SafeSubscribe('destroy')
|
|
60
|
+
export class MyObject {
|
|
61
|
+
constructor() {
|
|
62
|
+
interval(1000).safeSubscribe(this, () => {
|
|
63
|
+
console.log('This log will stop on object destroy.')
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
destroy() {}
|
|
70
67
|
}
|
|
71
68
|
```
|
|
72
69
|
|
|
70
|
+
## Api
|
|
71
|
+
|
|
72
|
+
### @SafeSubscribe(destructorName)
|
|
73
|
+
|
|
74
|
+
__Arguments__
|
|
75
|
+
|
|
76
|
+
* `destructorName: string` *(default: "ngOnDestroy")* - The name of the method that will called when the object is supposed to be destroyed.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### Observable.safeSubscribe(target, ...arguments): Subscription
|
|
81
|
+
|
|
82
|
+
__Arguments__
|
|
83
|
+
|
|
84
|
+
* `target: any` - A reference to the object that is holding the observable.
|
|
85
|
+
* `observerOrNext?: Observer|Function` - Either an observer with methods to be called, or the first of three possible handlers, which is the handler for each value emitted from the subscribed Observable.
|
|
86
|
+
* `error?: Function` - A handler for a terminal event resulting from an error. If no error handler is provided, the error will be thrown asynchronously as unhandled.
|
|
87
|
+
* `complete?: Function` - A handler for a terminal event resulting from successful completion.
|
|
88
|
+
|
|
89
|
+
__Return__
|
|
90
|
+
|
|
91
|
+
* A `Subscription` reference to the registered handler.
|
|
92
|
+
|
|
73
93
|
## Purpose
|
|
74
94
|
|
|
75
95
|
To quote a great [article](https://netbasal.com/when-to-unsubscribe-in-angular-d61c6b21bad3) from **Netanel Basal** :
|
|
@@ -94,3 +114,26 @@ There are a few exceptional observables where you don't need to unsubscribe :
|
|
|
94
114
|
However, as stated in the official Angular documentation :
|
|
95
115
|
|
|
96
116
|
> Feel free to unsubscribe anyway. It is harmless and never a bad practice !
|
|
117
|
+
|
|
118
|
+
## Contributing
|
|
119
|
+
|
|
120
|
+
#### > Want to Help ?
|
|
121
|
+
|
|
122
|
+
Want to file a bug, contribute some code or improve documentation ? Excellent!
|
|
123
|
+
|
|
124
|
+
But please read up first on the guidelines for [contributing][contributing], and learn about submission process, coding rules and more.
|
|
125
|
+
|
|
126
|
+
#### > Code of Conduct
|
|
127
|
+
|
|
128
|
+
Please read and follow the [Code of Conduct][codeofconduct] and help me keep this project open and inclusive.
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
[npm]: https://www.npmjs.com/package/@badisi/ngx-safe-subscribe
|
|
134
|
+
[npm-dl]: https://npmcharts.com/compare/@badisi/ngx-safe-subscribe?minimal=true
|
|
135
|
+
[ci-tests]: https://github.com/Badisi/ngx-safe-subscribe/actions/workflows/ci_tests.yml
|
|
136
|
+
[pullrequest]: https://github.com/badisi/ngx-safe-subscribe/blob/main/CONTRIBUTING.md#-submitting-a-pull-request-pr
|
|
137
|
+
[license]: https://github.com/Badisi/ngx-safe-subscribe/blob/main/LICENSE
|
|
138
|
+
[contributing]: https://github.com/badisi/latest-version/blob/main/CONTRIBUTING.md
|
|
139
|
+
[codeofconduct]: https://github.com/badisi/latest-version/blob/main/CODE_OF_CONDUCT.md
|
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import { Observable, Subscription } from 'rxjs';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const HAS_DECORATOR = Symbol('__safeSubscribeDecorator');
|
|
3
|
+
const SUBSCRIPTION = Symbol('__safeSubscribeSubscription$');
|
|
4
|
+
export function SafeSubscribe(destructorName = 'ngOnDestroy') {
|
|
5
|
+
return (classType) => {
|
|
6
|
+
const originalDestroy = classType.prototype[destructorName];
|
|
7
|
+
classType.prototype[destructorName] = function () {
|
|
8
|
+
originalDestroy && originalDestroy.call(this);
|
|
9
|
+
this[SUBSCRIPTION]?.unsubscribe();
|
|
10
|
+
this[SUBSCRIPTION] = null;
|
|
11
|
+
};
|
|
12
|
+
classType.prototype[HAS_DECORATOR] = true;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function safeSubscribe(target, ...args) {
|
|
16
|
+
const sub = this.subscribe(...args);
|
|
4
17
|
if (target) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
target.ngOnDestroy = function () {
|
|
12
|
-
if (originalDestroy && (typeof originalDestroy === 'function')) {
|
|
13
|
-
originalDestroy.apply(this, arguments);
|
|
14
|
-
}
|
|
15
|
-
target._subscriptionFromSafeSubscribe$.unsubscribe();
|
|
16
|
-
};
|
|
18
|
+
const hasDecorator = Object.getPrototypeOf(target)[HAS_DECORATOR];
|
|
19
|
+
if (!hasDecorator) {
|
|
20
|
+
throw new Error(`${target.constructor.name} class must be decorated with @SafeSubscribe() otherwise Observable<T>.safeSubscribe() will have no effect.`);
|
|
21
|
+
}
|
|
22
|
+
if (!target[SUBSCRIPTION]) {
|
|
23
|
+
target[SUBSCRIPTION] = new Subscription();
|
|
17
24
|
}
|
|
18
|
-
target.
|
|
25
|
+
target[SUBSCRIPTION].add(sub);
|
|
19
26
|
}
|
|
20
27
|
return sub;
|
|
21
28
|
}
|
|
22
29
|
Observable.prototype.safeSubscribe = safeSubscribe;
|
|
23
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXNhZmUtc3Vic2NyaWJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vbmd4LXNhZmUtc3Vic2NyaWJlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRWhELE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0FBQ3pELE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0FBUTVELE1BQU0sVUFBVSxhQUFhLENBQUMsY0FBYyxHQUFFLGFBQWE7SUFDdkQsT0FBTyxDQUFDLFNBQW1CLEVBQUUsRUFBRTtRQUMzQixNQUFNLGVBQWUsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzVELFNBQVMsQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLEdBQUc7WUFDbEMsZUFBZSxJQUFJLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDOUIsQ0FBQyxDQUFBO1FBQ0QsU0FBUyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsR0FBRyxJQUFJLENBQUM7SUFDOUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQztBQUVELE1BQU0sVUFBVSxhQUFhLENBQXlCLE1BQVcsRUFBRSxHQUFHLElBQVM7SUFDM0UsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3BDLElBQUksTUFBTSxFQUFFO1FBQ1IsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ2YsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSw2R0FBNkcsQ0FBQyxDQUFDO1NBQzVKO1FBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsRUFBRTtZQUN2QixNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztTQUM3QztRQUNELE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDakM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNmLENBQUM7QUFDRCxVQUFVLENBQUMsU0FBUyxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuY29uc3QgSEFTX0RFQ09SQVRPUiA9IFN5bWJvbCgnX19zYWZlU3Vic2NyaWJlRGVjb3JhdG9yJyk7XG5jb25zdCBTVUJTQ1JJUFRJT04gPSBTeW1ib2woJ19fc2FmZVN1YnNjcmliZVN1YnNjcmlwdGlvbiQnKTtcblxuZGVjbGFyZSBtb2R1bGUgJ3J4anMvaW50ZXJuYWwvT2JzZXJ2YWJsZScge1xuICAgIGludGVyZmFjZSBPYnNlcnZhYmxlPFQ+IHtcbiAgICAgICAgc2FmZVN1YnNjcmliZTogdHlwZW9mIHNhZmVTdWJzY3JpYmU7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gU2FmZVN1YnNjcmliZShkZXN0cnVjdG9yTmFtZSA9J25nT25EZXN0cm95Jyk6IENsYXNzRGVjb3JhdG9yIHtcbiAgICByZXR1cm4gKGNsYXNzVHlwZTogRnVuY3Rpb24pID0+IHtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxEZXN0cm95ID0gY2xhc3NUeXBlLnByb3RvdHlwZVtkZXN0cnVjdG9yTmFtZV07XG4gICAgICAgIGNsYXNzVHlwZS5wcm90b3R5cGVbZGVzdHJ1Y3Rvck5hbWVdID0gZnVuY3Rpb24gKHRoaXM6IGFueSkge1xuICAgICAgICAgICAgb3JpZ2luYWxEZXN0cm95ICYmIG9yaWdpbmFsRGVzdHJveS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgdGhpc1tTVUJTQ1JJUFRJT05dPy51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgdGhpc1tTVUJTQ1JJUFRJT05dID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjbGFzc1R5cGUucHJvdG90eXBlW0hBU19ERUNPUkFUT1JdID0gdHJ1ZTtcbiAgICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FmZVN1YnNjcmliZTxUPih0aGlzOiBPYnNlcnZhYmxlPFQ+LCB0YXJnZXQ6IGFueSwgLi4uYXJnczogYW55KTogU3Vic2NyaXB0aW9uIHtcbiAgICBjb25zdCBzdWIgPSB0aGlzLnN1YnNjcmliZSguLi5hcmdzKTtcbiAgICBpZiAodGFyZ2V0KSB7XG4gICAgICAgIGNvbnN0IGhhc0RlY29yYXRvciA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih0YXJnZXQpW0hBU19ERUNPUkFUT1JdO1xuICAgICAgICBpZiAoIWhhc0RlY29yYXRvcikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RhcmdldC5jb25zdHJ1Y3Rvci5uYW1lfSBjbGFzcyBtdXN0IGJlIGRlY29yYXRlZCB3aXRoIEBTYWZlU3Vic2NyaWJlKCkgb3RoZXJ3aXNlIE9ic2VydmFibGU8VD4uc2FmZVN1YnNjcmliZSgpIHdpbGwgaGF2ZSBubyBlZmZlY3QuYCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0YXJnZXRbU1VCU0NSSVBUSU9OXSkge1xuICAgICAgICAgICAgdGFyZ2V0W1NVQlNDUklQVElPTl0gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGFyZ2V0W1NVQlNDUklQVElPTl0uYWRkKHN1Yik7XG4gICAgfVxuICAgIHJldHVybiBzdWI7XG59XG5PYnNlcnZhYmxlLnByb3RvdHlwZS5zYWZlU3Vic2NyaWJlID0gc2FmZVN1YnNjcmliZTtcbiJdfQ==
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
import { Subscription, Observable } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const HAS_DECORATOR = Symbol('__safeSubscribeDecorator');
|
|
4
|
+
const SUBSCRIPTION = Symbol('__safeSubscribeSubscription$');
|
|
5
|
+
function SafeSubscribe(destructorName = 'ngOnDestroy') {
|
|
6
|
+
return (classType) => {
|
|
7
|
+
const originalDestroy = classType.prototype[destructorName];
|
|
8
|
+
classType.prototype[destructorName] = function () {
|
|
9
|
+
var _a;
|
|
10
|
+
originalDestroy && originalDestroy.call(this);
|
|
11
|
+
(_a = this[SUBSCRIPTION]) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
12
|
+
this[SUBSCRIPTION] = null;
|
|
13
|
+
};
|
|
14
|
+
classType.prototype[HAS_DECORATOR] = true;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function safeSubscribe(target, ...args) {
|
|
18
|
+
const sub = this.subscribe(...args);
|
|
5
19
|
if (target) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
target.ngOnDestroy = function () {
|
|
13
|
-
if (originalDestroy && (typeof originalDestroy === 'function')) {
|
|
14
|
-
originalDestroy.apply(this, arguments);
|
|
15
|
-
}
|
|
16
|
-
target._subscriptionFromSafeSubscribe$.unsubscribe();
|
|
17
|
-
};
|
|
20
|
+
const hasDecorator = Object.getPrototypeOf(target)[HAS_DECORATOR];
|
|
21
|
+
if (!hasDecorator) {
|
|
22
|
+
throw new Error(`${target.constructor.name} class must be decorated with @SafeSubscribe() otherwise Observable<T>.safeSubscribe() will have no effect.`);
|
|
23
|
+
}
|
|
24
|
+
if (!target[SUBSCRIPTION]) {
|
|
25
|
+
target[SUBSCRIPTION] = new Subscription();
|
|
18
26
|
}
|
|
19
|
-
target.
|
|
27
|
+
target[SUBSCRIPTION].add(sub);
|
|
20
28
|
}
|
|
21
29
|
return sub;
|
|
22
30
|
}
|
|
@@ -26,5 +34,5 @@ Observable.prototype.safeSubscribe = safeSubscribe;
|
|
|
26
34
|
* Generated bundle index. Do not edit.
|
|
27
35
|
*/
|
|
28
36
|
|
|
29
|
-
export { safeSubscribe };
|
|
37
|
+
export { SafeSubscribe, safeSubscribe };
|
|
30
38
|
//# sourceMappingURL=badisi-ngx-safe-subscribe.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badisi-ngx-safe-subscribe.mjs","sources":["../../ngx-safe-subscribe.ts","../../badisi-ngx-safe-subscribe.ts"],"sourcesContent":["import { Observable, Subscription } from 'rxjs';\n\ndeclare module 'rxjs/internal/Observable' {\n interface Observable<T> {\n safeSubscribe: typeof safeSubscribe;\n }\n}\n\nexport
|
|
1
|
+
{"version":3,"file":"badisi-ngx-safe-subscribe.mjs","sources":["../../ngx-safe-subscribe.ts","../../badisi-ngx-safe-subscribe.ts"],"sourcesContent":["import { Observable, Subscription } from 'rxjs';\n\nconst HAS_DECORATOR = Symbol('__safeSubscribeDecorator');\nconst SUBSCRIPTION = Symbol('__safeSubscribeSubscription$');\n\ndeclare module 'rxjs/internal/Observable' {\n interface Observable<T> {\n safeSubscribe: typeof safeSubscribe;\n }\n}\n\nexport function SafeSubscribe(destructorName ='ngOnDestroy'): ClassDecorator {\n return (classType: Function) => {\n const originalDestroy = classType.prototype[destructorName];\n classType.prototype[destructorName] = function (this: any) {\n originalDestroy && originalDestroy.call(this);\n this[SUBSCRIPTION]?.unsubscribe();\n this[SUBSCRIPTION] = null;\n }\n classType.prototype[HAS_DECORATOR] = true;\n };\n}\n\nexport function safeSubscribe<T>(this: Observable<T>, target: any, ...args: any): Subscription {\n const sub = this.subscribe(...args);\n if (target) {\n const hasDecorator = Object.getPrototypeOf(target)[HAS_DECORATOR];\n if (!hasDecorator) {\n throw new Error(`${target.constructor.name} class must be decorated with @SafeSubscribe() otherwise Observable<T>.safeSubscribe() will have no effect.`);\n }\n if (!target[SUBSCRIPTION]) {\n target[SUBSCRIPTION] = new Subscription();\n }\n target[SUBSCRIPTION].add(sub);\n }\n return sub;\n}\nObservable.prototype.safeSubscribe = safeSubscribe;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './ngx-safe-subscribe';\n"],"names":[],"mappings":";;AAEA,MAAM,aAAa,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAC;AACzD,MAAM,YAAY,GAAG,MAAM,CAAC,8BAA8B,CAAC,CAAC;AAQ5C,SAAA,aAAa,CAAC,cAAc,GAAE,aAAa,EAAA;IACvD,OAAO,CAAC,SAAmB,KAAI;QAC3B,MAAM,eAAe,GAAG,SAAS,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;AAC5D,QAAA,SAAS,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,YAAA;;AAClC,YAAA,eAAe,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9C,YAAA,CAAA,EAAA,GAAA,IAAI,CAAC,YAAY,CAAC,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,WAAW,EAAE,CAAC;AAClC,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;AAC9B,SAAC,CAAA;AACD,QAAA,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;AAC9C,KAAC,CAAC;AACN,CAAC;SAEe,aAAa,CAAyB,MAAW,EAAE,GAAG,IAAS,EAAA;IAC3E,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;AACpC,IAAA,IAAI,MAAM,EAAE;QACR,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,EAAE;YACf,MAAM,IAAI,KAAK,CAAC,CAAG,EAAA,MAAM,CAAC,WAAW,CAAC,IAAI,CAA6G,2GAAA,CAAA,CAAC,CAAC;AAC5J,SAAA;AACD,QAAA,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE;AACvB,YAAA,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,YAAY,EAAE,CAAC;AAC7C,SAAA;QACD,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACjC,KAAA;AACD,IAAA,OAAO,GAAG,CAAC;AACf,CAAC;AACD,UAAU,CAAC,SAAS,CAAC,aAAa,GAAG,aAAa;;ACrClD;;AAEG;;;;"}
|
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
import { Subscription, Observable } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const HAS_DECORATOR = Symbol('__safeSubscribeDecorator');
|
|
4
|
+
const SUBSCRIPTION = Symbol('__safeSubscribeSubscription$');
|
|
5
|
+
function SafeSubscribe(destructorName = 'ngOnDestroy') {
|
|
6
|
+
return (classType) => {
|
|
7
|
+
const originalDestroy = classType.prototype[destructorName];
|
|
8
|
+
classType.prototype[destructorName] = function () {
|
|
9
|
+
originalDestroy && originalDestroy.call(this);
|
|
10
|
+
this[SUBSCRIPTION]?.unsubscribe();
|
|
11
|
+
this[SUBSCRIPTION] = null;
|
|
12
|
+
};
|
|
13
|
+
classType.prototype[HAS_DECORATOR] = true;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function safeSubscribe(target, ...args) {
|
|
17
|
+
const sub = this.subscribe(...args);
|
|
5
18
|
if (target) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
target.ngOnDestroy = function () {
|
|
13
|
-
if (originalDestroy && (typeof originalDestroy === 'function')) {
|
|
14
|
-
originalDestroy.apply(this, arguments);
|
|
15
|
-
}
|
|
16
|
-
target._subscriptionFromSafeSubscribe$.unsubscribe();
|
|
17
|
-
};
|
|
19
|
+
const hasDecorator = Object.getPrototypeOf(target)[HAS_DECORATOR];
|
|
20
|
+
if (!hasDecorator) {
|
|
21
|
+
throw new Error(`${target.constructor.name} class must be decorated with @SafeSubscribe() otherwise Observable<T>.safeSubscribe() will have no effect.`);
|
|
22
|
+
}
|
|
23
|
+
if (!target[SUBSCRIPTION]) {
|
|
24
|
+
target[SUBSCRIPTION] = new Subscription();
|
|
18
25
|
}
|
|
19
|
-
target.
|
|
26
|
+
target[SUBSCRIPTION].add(sub);
|
|
20
27
|
}
|
|
21
28
|
return sub;
|
|
22
29
|
}
|
|
@@ -26,5 +33,5 @@ Observable.prototype.safeSubscribe = safeSubscribe;
|
|
|
26
33
|
* Generated bundle index. Do not edit.
|
|
27
34
|
*/
|
|
28
35
|
|
|
29
|
-
export { safeSubscribe };
|
|
36
|
+
export { SafeSubscribe, safeSubscribe };
|
|
30
37
|
//# sourceMappingURL=badisi-ngx-safe-subscribe.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badisi-ngx-safe-subscribe.mjs","sources":["../../ngx-safe-subscribe.ts","../../badisi-ngx-safe-subscribe.ts"],"sourcesContent":["import { Observable, Subscription } from 'rxjs';\n\ndeclare module 'rxjs/internal/Observable' {\n interface Observable<T> {\n safeSubscribe: typeof safeSubscribe;\n }\n}\n\nexport
|
|
1
|
+
{"version":3,"file":"badisi-ngx-safe-subscribe.mjs","sources":["../../ngx-safe-subscribe.ts","../../badisi-ngx-safe-subscribe.ts"],"sourcesContent":["import { Observable, Subscription } from 'rxjs';\n\nconst HAS_DECORATOR = Symbol('__safeSubscribeDecorator');\nconst SUBSCRIPTION = Symbol('__safeSubscribeSubscription$');\n\ndeclare module 'rxjs/internal/Observable' {\n interface Observable<T> {\n safeSubscribe: typeof safeSubscribe;\n }\n}\n\nexport function SafeSubscribe(destructorName ='ngOnDestroy'): ClassDecorator {\n return (classType: Function) => {\n const originalDestroy = classType.prototype[destructorName];\n classType.prototype[destructorName] = function (this: any) {\n originalDestroy && originalDestroy.call(this);\n this[SUBSCRIPTION]?.unsubscribe();\n this[SUBSCRIPTION] = null;\n }\n classType.prototype[HAS_DECORATOR] = true;\n };\n}\n\nexport function safeSubscribe<T>(this: Observable<T>, target: any, ...args: any): Subscription {\n const sub = this.subscribe(...args);\n if (target) {\n const hasDecorator = Object.getPrototypeOf(target)[HAS_DECORATOR];\n if (!hasDecorator) {\n throw new Error(`${target.constructor.name} class must be decorated with @SafeSubscribe() otherwise Observable<T>.safeSubscribe() will have no effect.`);\n }\n if (!target[SUBSCRIPTION]) {\n target[SUBSCRIPTION] = new Subscription();\n }\n target[SUBSCRIPTION].add(sub);\n }\n return sub;\n}\nObservable.prototype.safeSubscribe = safeSubscribe;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './ngx-safe-subscribe';\n"],"names":[],"mappings":";;AAEA,MAAM,aAAa,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAC;AACzD,MAAM,YAAY,GAAG,MAAM,CAAC,8BAA8B,CAAC,CAAC;AAQ5C,SAAA,aAAa,CAAC,cAAc,GAAE,aAAa,EAAA;IACvD,OAAO,CAAC,SAAmB,KAAI;QAC3B,MAAM,eAAe,GAAG,SAAS,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;AAC5D,QAAA,SAAS,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,YAAA;AAClC,YAAA,eAAe,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9C,YAAA,IAAI,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;AAClC,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;AAC9B,SAAC,CAAA;AACD,QAAA,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;AAC9C,KAAC,CAAC;AACN,CAAC;SAEe,aAAa,CAAyB,MAAW,EAAE,GAAG,IAAS,EAAA;IAC3E,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;AACpC,IAAA,IAAI,MAAM,EAAE;QACR,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,EAAE;YACf,MAAM,IAAI,KAAK,CAAC,CAAG,EAAA,MAAM,CAAC,WAAW,CAAC,IAAI,CAA6G,2GAAA,CAAA,CAAC,CAAC;AAC5J,SAAA;AACD,QAAA,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE;AACvB,YAAA,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,YAAY,EAAE,CAAC;AAC7C,SAAA;QACD,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACjC,KAAA;AACD,IAAA,OAAO,GAAG,CAAC;AACf,CAAC;AACD,UAAU,CAAC,SAAS,CAAC,aAAa,GAAG,aAAa;;ACrClD;;AAEG;;;;"}
|
package/ngx-safe-subscribe.d.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { Subscription } from 'rxjs';
|
|
1
|
+
import { Observable, Subscription } from 'rxjs';
|
|
2
2
|
declare module 'rxjs/internal/Observable' {
|
|
3
3
|
interface Observable<T> {
|
|
4
4
|
safeSubscribe: typeof safeSubscribe;
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
ngOnDestroy(): void;
|
|
10
|
-
}
|
|
11
|
-
export declare function safeSubscribe<T>(target: SafeSubscribable, next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;
|
|
7
|
+
export declare function SafeSubscribe(destructorName?: string): ClassDecorator;
|
|
8
|
+
export declare function safeSubscribe<T>(this: Observable<T>, target: any, ...args: any): Subscription;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@badisi/ngx-safe-subscribe",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Easy way to automatically unsubscribe from RxJS observables in Angular components",
|
|
5
5
|
"homepage": "https://github.com/badisi/ngx-safe-subscribe",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"safesubscribe"
|
|
24
24
|
],
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@angular/core": ">=14.0.0",
|
|
27
|
-
"rxjs": ">=6.0.0"
|
|
26
|
+
"@angular/core": ">= 14.0.0",
|
|
27
|
+
"rxjs": ">= 6.0.0"
|
|
28
28
|
},
|
|
29
29
|
"module": "fesm2015/badisi-ngx-safe-subscribe.mjs",
|
|
30
30
|
"es2020": "fesm2020/badisi-ngx-safe-subscribe.mjs",
|