rxjs operator which notifies one value when uptream completes - rxjs

I have a stream myStream which does some work but does not notify anything and, at the end of the work, completes.
I am looking for an operator which can listen the complete of myStream and, at that moment, notifies a value, something like this
myStream.pipe(
operatorThatNotifiesWhenUpstreamCompletes('Upstream has completed')
).subscribe(console.log) // prints 'Upstream has completed'

Sounds like you're looking for defaultIfEmpty() :).

Related

Do RxJS observers always process all events submitted before the observable is completed?

I want to make sure that all events, which were submitted before complete was invoked on the observable, are logged.
I'm aware that operators exist that stop emission of events (takeUntil, etc.) completely.
The question that I have is whether other operators exist which would lead to emissions not being sent if the complete on the subject is sent too 'early'. Are there cases where it would be beneficial to wait with the completion of the observable until the event was handled by the observer?
For example, are there situations (imagine any other RxJS operator instead of the delay) where the following code ...
const subj = new Subject<string>();
subj.pipe(delay(500))
.subscribe((val) => {
console.log(val);
subj.complete();
});
subj.next('1');
... makes more sense than that ...
const subj = new Subject<string>();
subj.pipe(delay(500))
.subscribe((val) => {
console.log(val);
});
subj.next('1');
subj.complete();
... when the subject should only emit one value?
Or is completing the subject immediately after next always safe in such situations?
If there are other factors I'm not aware of (e.g. synchronous vs. asynchronous execution of code) please mention them as well.
In general,
subj.next('1');
subj.complete();
is safe. As far as I know, none of the existing RxJS operators use a completion to cancel/unsubscribe observables early.
That being said, I can easily create such an operator myself. switchMap will cancel currently running inner observables when it receives it's next emission. You could, for example, create a custom operator that unsubscribes and exists early when it receives a complete event.
If your worried about that, however, you're out of luck. No matter what workaround you imagine, I can probably write an operator that will ruin your code. For example filter(_ => false) will stop the 1 from being emitted before the complete in either of the two cases you've described.
In the end, you and your coworkers must write good code (and test!) and RxJS doesn't change that.

Is it safe/okay to combine take(1) and defaultIfEmpty when subscribing to Observable<boolean>?

I am using the following code to basically ensure that I get a result from an Observable
this.authenticationService.isLoggedIn
.pipe(
take(1),
defaultIfEmpty(false)
)
.subscribe(result => return result);
Somehow it feels wrong to me, maybe because it seems sort of procedural.
Is this method okay? Will this get me in trouble in any way?
If in your code it's fine that this.authenticationService.isLoggedIn completes without an emit - then the code in your question is fine too.
If this.authenticationService.isLoggedIn emits anything at some point of time and completes after - then defaultIfEmpty is redundant.
It all depends on what isLoggedIn does.
It is clear that isLoggedIn returns an Observable.
Now, and Observable can do just 3 things
it can notify, i.e. emit, some data for consumption of Observers which are subscribed
it can raise an error
it can complete
So the first question is: how many times can isLoggedIn notify? Is it just one shot or is it a stream of notifications? If it can emit just one value and then complete, than the take(1) operator is useless.
But there is also the case that isLoggedIn never notifies and just completes. In this case a notification would never be signaled by the observer to its subscriber. Using defaultIfEmpty operator ensures that something is notified even in this case.
So, reading your code I understand that isLoggedIn can behave in these 2 ways
Emit more than once but you are interested only in the first notification
Never notify and just complete, in which case you want false to be returned
If this is not true, it may be the case that your code can be simplified.

Process a stream of events after a Start event and return to listen when an End event occurs

The scenario I am working on is composed by 3 Observables.
StartObs: this Observable emits when I need to start a sequence of processings - the data emitted is a processID of the process I need to fulfill
DoStuffObs: this Observable emits commands upon which I have to do something - I want to start listening to such Observable just after StartObs has emitted and I need the processID of the process to perform my duties with the function doTheWork(command, processId)
EndObs: this Observable emits when I have to end the processing of a certain processID and have to go back to listen to the next emission of StartObs
So basically is: Start, DoStuff until End and then go back to listening to the next Start.
It is also guaranteed that after one Start comes sooner or later one End and that it is not possible to have 2 Start without an End in between or 2 End without a Start in between.
The first 2 steps can be achieved via switchMap, like
StartObs
.switchMap(processId => DoStuff.map(command => ({command, processId})))
.tap(data => doTheWork(data.command, data.processId))
What is not clear to me is how to deal with EndObs.
The option of using takeUntil does not work, since I do not want to complete the chain started with StartObs since I have to go back to listening for the next process to start.
Actually, I think takeUntil() is the best choice here in combination with repeat().
StartObs
.switchMap(processId => DoStuff.map(command => ({command, processId})))
.tap(data => doTheWork(data.command, data.processId))
.takeUntil(EndObs)
.repeat();
When the chain completes with takeUntil() it will immediately resubscribe thanks to repeat() and the whole process will start all over again.

Observing when stream is unsubscribed

I have an RxJS observable stream that I'm sharing like the following:
var sub = Observable.create(obs => {
// logic here
return () => {
// call rest service to notify server
};
})
.publish()
.refCount();
When the last subscriber unsubscribes, I need to make a REST request. The obvious choice is to add that call into the return cleanup function - but you then have broken out of any observable sequence and any errors etc aren't easily handled.
I could just use a Subject, push a value onto it in the cleanup function, and observe it elsewhere with the REST call hanging off that.
Ideally I'd do something like concatenating to the disposed stream with my REST call (concat obviously wouldn't work as it's not completing).
Does anyone have any suggestions for the cleanest way of handling this? All the options above seem a bit clunky and I feel like I've missed something.
You could implement a finally(...) in your stream, that does the cleanup.
The finally is automatically executed when the stream finalizes (error or complete).
Note: This will not work when you unsubscribe manually and not call complete on your stream.

Conditional transition in MassTransit Automatonymous saga

I have some state in the saga and trying to implement status check retries until I get some satisfactory value in a message I receved.
Say, I have something like this:
.During(Pending,
When(StatusChecked)
.TransitionTo(somethingThatDependsOnStatusCheckedData)
I can only feed a specific state to TransitionTo but I want it to transition depending on the received message content, is it possible?
For received message content, you can use the conditional expression on the When clause.
During(Pending,
When(StatusChecked, context => context.Data.IsMessageCondition)
.Then(...));

Resources