I am building an Angular application and I have a route, protected with guard. In the guard I have 3 boolean observables.
Each observable returns true or false values, depending on the application state/route etc. I want that the guard returns true, if at least one observable returned true, otherwise - false.
So if at least one observables has evaluated to true - I want that the script should ignore others and the guard should return true
But if it returned false, the guard should look for the second observable and see its evaluated result.
I think that I could use combineLatest
:
combineLatest([
$obs1,
$obs2,
$obs3
])
and check result of each observable, but this code will run all three observables without cancellation.
the observables may run simultaneously, but they must not complete (if not already completed, if any of observables already returned true
,
and should return false
only if all of observables returns false
).
Which operator should I use for getting the first true
observable value, and ignoring others, but returning false if all observables returned false
?
CodePudding user response:
I think what you are trying to achieve could be done with
merge(
$obs1.pipe(first()),
$obs2.pipe(first()),
$obs3.pipe(first())
).pipe(
filter(Boolean),
take(1),
defaultIfEmpty(false),
)
filter(Boolean)
filters out false
results, because there are probably yet not handled true
s and we should continue searching.
take(1)
will take the first true
when found, because you really don't care about other trues if there is already one.
and if everything is false, then no events will be emmited by previous operator chain and therefore defaultIfEmpty(false)
will put false in that place
CodePudding user response:
combineLatest
should be what you want !
combineLatest([obs1$, obs2$, obs3$]).pipe(
filter(([v1, v2, v3]) => {
return v1 || v2 || v3 || (!v1 && !v2 && !v3);
}),
take(1)
);