-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(tap): Adds subscribe, unsubscribe, finalize handlers #6527
feat(tap): Adds subscribe, unsubscribe, finalize handlers #6527
Conversation
This adds a common request/task for RxJS users, which are three new handlers: - `subscribe`: fires on subscription to the source - `unsubscribe`: fires when the subscription to the result is unsubscribed from, but NOT if the source completes or errors - `finalize`: always fires on finalization, (basically equivalent to `finalize`)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the reasoning behind doing this only for the tap operator and not for Subscribable.subscribe?
src/internal/operators/tap.ts
Outdated
isFunction(observerOrNext) || error || complete | ||
? // tslint:disable-next-line: no-object-literal-type-assertion | ||
({ next: observerOrNext as Exclude<typeof observerOrNext, Partial<TapObserver<T>>>, error, complete } as Partial<TapObserver<T>>) | ||
: observerOrNext; | ||
|
||
// TODO: Use `operate` function once this PR lands: https://github.com/ReactiveX/rxjs/pull/5742 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: i think this comment can be removed
Just checking: did we discuss this in core meeting? |
@backbone87 the main reasoning is we're not attempting to change the semantics of observable, (which import { interval, share, tap, take } from 'rxjs';
const producer = interval(1000).pipe(
share(),
take(100),
tap({
unsubscribe: () => console.log('a user has unsubscribed'),
})
);
// At this point `producer` could be handed off to anyone.
// `tap` is concerned with side effects that _producer_ needs. Not the consumer.
// Here we have a consumer
const subscription = producer.subscribe({
next: console.log,
// (hypothetical)
unsubscribe: () => console.log('you unsubscribed yourself')
});
// Why didn't you just console log here? :shrug:
subscription.unsubscribe(); the producer.subscribe({
// Hypothetical:
subscribe: () => console.log('you subscribed, lol');
}); Finalize might have merit however, and that's possibly worth discussing. Interestingly, it can be handled now like so (it's just non-obvious): const subscription = producer.subscribe(console.log);
subscription.add(() => console.log('finalized'); In the future if we're using AbortSignal, and we land on not minding async completion (That's probably a non-starter), we could leverage // Hypothetical
const controller = new AbortControlelr();
const { signal } = controller;
producer.forEach(console.log, { signal }).finally(() => console.log('finalized')) You can obviously do this now with |
Yes, but it's been a long time since we did. |
This adds a common request/task for RxJS users, which are three new handlers:
subscribe
: fires on subscription to the sourceunsubscribe
: fires when the subscription to the result is unsubscribed from, but NOT if the source completes or errorsfinalize
: always fires on finalization, (basically equivalent tofinalize
)This is useful for situations where you'd like to know that your consumer has decided to unsubscribe (and you're not terminating because of a complete or an error).
See included tests for more information.