New Abstractions: Effect, QueueingEffect, SwitchingEffect, BlockingEffect #7438
deanrad
started this conversation in
Ideas / Feature request
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
RxJS - despite many internal improvements over a dozen years - hasn’t grown much in its level of abstraction, and this keeps it hard to learn, and makes devs inclined to reimplement it. RxJS still deals in
pipe
s, Subjects and obscurely-named operators which no amount of documentation seems to sort out for developers, and I think it can provide a shorter on-ramp than it does.This PR aims to introduce an abstraction -
Effect
, and its concurrency-controlled kin likeQueueingEffect
- that makes the desirable and common use-cases of concurrency control and cancelation easier, with fewer imports, more mnemonic names, and more direct cancelation. (It could be extended to a version that keeps track of state such asStatefulQueueingEffect
- but that will be proposed separately).How does it work? Imagine a function
playBellSound
that plays a bell ringing sound. We want to use aconcatMap
style of behavior to reduce concurrency to 1 by enqueueing rings one after another. Under this proposal, this would be:Without this proposal, the status quo is:
Only one of these: a) highlights the concurrency mode b) names it plainly c) is free of noise words like
pipe
andsubscribe
.Let’s introduce cancelation, and the contrast will only increase. Under the new proposal:
While the status quo would be:
The number of imports has grown, as well as the noisiness of the code. This shows there is an abstraction just begging to be factored out - why not provide it inside RxJS so that people can have a simpler initial interface?
Lastly, if a user may want to cancel the bell, they may want to cancel the entire queue. This could be simply:
While the raw RxJS of canceling the queue probably involves a new Subject, a
switchMap
, and other code contortions. (See this StackOverflow thread for community-proposed versions.)In this proposal, each of the
*map
operators would have a corresponding effect:mergeMap
concatMap
switchMap
exhaustMap
They would share the same interface, where the single argument would be a function returning an
ObservableInput
of a Promise, Observable, etc.. and the return value would be an object with anext()
method, which would forward its arguments through to the underlying effect.Sample (but not minimal) implementation code is provided in the
@rxfx/service
library RxFx Github - my own ‘contrib’ library. A Service, in RxFx, concurrency controls an effect as in this proposal, but also accepts a reducer to keep track of astate
Observable by aggregating over lifecycle events of the effect viascan
.In short - I don’t think the answer to a shorter learning curve for RxJS is only in having better documentation, or having more blog posts claiming to demystify Observables - I think it’s having abstractions that are more self-explanatory.
Let me know if this is something we can consider for an enhancement to RxJS or if there’s another repo you think this would be more suited to. Thanks.
PS Regarding Error handling, it's worth discussing whether an error should finalize the effect (as if it were a Subject), or if the effect should try and be more generous - rescuing errors by default and making them available through some property like an
.errors
Observable.Beta Was this translation helpful? Give feedback.
All reactions