You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(no-ignored-subscription): ignore for certain operators (#187)
This adds new options and default behavior to `no-ignored-subscription`
so that operators like `takeUntil` or `first` will silence this rule.
The main new option, `completers`, specifies which operators should
silence this rule because they complete the observable automatically. By
default, we've set `completers` to allow `takeUntil`, `takeWhile`,
`take`, `first`, `last`, and Angular's `takeUntilDestroyed`.
Additionally, we are using the same logic that's used for
`no-unsafe-takeuntil`: if you place another operator _after_ one of
these "completers", then this rule will consider the subscription not
properly handled and will trigger.
The other new option, `postCompleters`, specifies which operators can be
placed _after_ a "completer" and still prevent this rule from
triggering. By default, we've set `postCompleters` to the same set of
defaults used by `no-unsafe-takeuntil` (things like `share`, `finalize`,
etc).
Example of new allowed functionality:
```ts
import { BehaviorSubject, first } from 'rxjs';
const foo$ = new BehaviorSubject('foo');
foo$
.pipe(first())
.subscribe(() => console.log('first!'));
// Logs 'first!' and then unsubscribes.
```
Example of more complicated functionality that still doesn't trigger
this rule:
```ts
import { interval, Subject, takeUntil, share } from 'rxjs';
const stop$ = new Subject();
interval(1000)
.pipe(
takeUntil(stop$),
max(),
).subscribe(x => console.log('max: ', x));
stop$.next();
// Logs the last value of the interval at the time when you called stop$ and then unsubscribes.
```
Note: there's relevant upstream conversation here:
cartant#39 . The original
author rejected this feature, but I found that re-using
`no-unsafe-takeuntil`'s algorithm for "what is a valid last operator"
was straightforward. I'm open to feedback if there's serious overlooked
edge cases, but it seems like a workable solution for simple cases.
Additional work in this PR: refactored `utils.ts` into separate files
with a `utils/index.ts` entrypoint.
Resolves#60
|`completers`| An array of operator names that will complete the observable and silence this rule. | String[]|[`takeUntil`, `takeWhile`, `take`, `first`, `last`, `takeUntilDestroyed`]|
54
+
|`postCompleters`| An array of operator names that are allowed to follow the completion operators. | String[]|[`count`, `defaultIfEmpty`, `endWith`, `every`, `finalize`, `finally`, `isEmpty`, `last`, `max`, `min`, `publish`, `publishBehavior`, `publishLast`, `publishReplay`, `reduce`, `share`, `shareReplay`, `skipLast`, `takeLast`, `throwIfEmpty`, `toArray`]|
55
+
56
+
<!-- end auto-generated rule options list -->
57
+
35
58
## When Not To Use It
36
59
37
60
If you don't care about unsubscribing from all observables in your project, then you may not need this rule.
38
-
Alternatively, your project might use operators like `take`, `takeUntil`, `takeWhile`, etc.
39
-
or Angular's `takeUntilDestroyed` to automatically handle subscriptions.
61
+
Alternatively, your project might compose observables with operators like `take`, `takeUntil`, `takeWhile`, etc.
62
+
or [Angular's `takeUntilDestroyed`](https://angular.dev/api/core/rxjs-interop/takeUntilDestroyed)
63
+
and then call `subscribe` elsewhere, which cannot be detected by this rule.
40
64
41
65
Type checked lint rules are more powerful than traditional lint rules, but also require configuring type checked linting.
forbidden: 'Ignoring returned subscriptions is forbidden.',
14
21
},
15
-
schema: [],
22
+
schema: [
23
+
{
24
+
properties: {
25
+
completers: {type: 'array',items: {type: 'string'},description: 'An array of operator names that will complete the observable and silence this rule.',default: ['takeUntil','takeWhile','take','first','last','takeUntilDestroyed']},
26
+
postCompleters: {type: 'array',items: {type: 'string'},description: 'An array of operator names that are allowed to follow the completion operators.',default: DEFAULT_VALID_POST_COMPLETION_OPERATORS},
27
+
},
28
+
type: 'object',
29
+
description: stripIndent`
30
+
An object with optional \`completers\` and \`postCompleters\` properties.
31
+
The \`completers\` property is an array containing the names of operators that will complete the observable and silence this rule.
32
+
The \`postCompleters\` property is an array containing the names of the operators that are allowed to follow the completion operators.
alias: {type: 'array',items: {type: 'string'},description: 'An array of operator names that should be treated similarly to `takeUntil`.'},
55
-
allow: {type: 'array',items: {type: 'string'},description: 'An array of operator names that are allowed to follow `takeUntil`.',default: allowedOperators},
29
+
allow: {type: 'array',items: {type: 'string'},description: 'An array of operator names that are allowed to follow `takeUntil`.',default: DEFAULT_VALID_POST_COMPLETION_OPERATORS},
0 commit comments