Here's the scenario: there are two observable streams (A and B). I want to only emit from B after A has emitted at least once.
I tried combineLatest, but the problem with that was that the combined stream emitted when either A or B emitted. I only want this stream to emit when B emits, I do not need the value from A. I just need it to have been emitted once.
This is what I am looking for:
---a---a-- A
-b---b---- B
---b-b---- required
I think this should work:
combineLatest(a$.pipe(first()), b$)
.pipe(
map(([a, b]) => b)
)
combineLatest will emit for the first time when both a$ and b$ would have emitted, then it will only emit when b$ emits, due to a$.pipe(first()).
Once the combine latest emits then switch back to b.
combineLatest(a$, b$).pipe(
map(([a, b]) => b),
switchMap(_ => b$)
);
Related
I have 2 observables A and B which can emit at any time. But only when A emits a new value and then B emits a new value too, I collect these 2 values. If B just emits new values without A emitting new values first, I don't collect any values.
I know concatMap might be useful but it needs the previous observable to complete whereas in my case neither ever completes until everything is destroyed.
This can be modelled as projecting each element of A into the first arriving element of B, discarding any previous subscription to B when a new A arrives, e.g.:
A.pipe(
switchMap(x => B.pipe(
first(),
map(y => ({ a: x, b: y }))
)
)
To make my specific condition as easy as possible I have the following observables.
const a = of(true);
const b = of(true);
I am looking to determine that if either or both of these are true then return an observable of true but if both are false, return an observable of false.
if (a || b) ? true : false;
I seem to be tripping over how to combine them correctly, I was using combineLatest to get an array.
combineLatest([
a,
b,
])
// [true, true]
I think that https://xgrommx.github.io/rx-book/content/observable/observable_instance_methods/some.html is what I need but that seems long gone and searching for "some" isn't amazing.
combineLatest([
a,
b,
]).pipe(
some(x => x === true)
)
You can use combineLatest to produce single observable based on multiple source observables:
const myBool$ = combineLatest([a$, b$]).pipe(
map(([a, b]) => a || b)
);
Your combined observable will emit an array of values whenever any of the sources emit (note it won't emit for the first time until each source emits at least once). You can then use the map operator to transform the emitted array into your single boolean.
The code above will emit the boolean value whenever any source emits. However, it may not be desirable to receive emissions if the resultant value hasn't changes (ex: if a and b are both true, then b changes to false, the result is still true).
We can prevent emitting the same result by using distinctUntilChanged:
const myBool$ = combineLatest([a$, b$]).pipe(
map(([a, b]) => a || b),
distinctUntilChanged()
);
Let's say I have the following : https://stackblitz.com/edit/concat
import {concat} from "rxjs/observable/concat";
import {fullObserver, stream} from "./utils";
const a = stream('a', 200, 3, 'partial');
const b = stream('b', 200, 3, 'partial');
concat(a, b).subscribe(fullObserver('concat'));
This will, subscribe to a, give me the result of a, then subscribe to b, and get the b result.
but, how do I do the follow,
subscribe to a => a complete
subscribe to b => b complete
get the result of a and b in an array like when booth are completed
its like a forkJoin but with a concat, so that all subscription are sequential. How could I do ?
There's toArray() operator that will collect all next notifications and re-emit them in a single array after its source completes (concat will complete after all its source complete).
So in your case it will look like this:
concat(a, b).pipe(toArray()).subscribe(fullObserver('concat'));
Btw, you don't need to be importing "creation operators" such as concat or timer from rxjs/observable/* and you import them from just rxjs.
Let's say there are 2 observables, observable A and observable B.
When A emits a value, I want to wait 1 second, and then emit the latest value of B. If A emits another value while waiting 1 second, I want it to forget about the previous value and wait another 1 second (like switchMap does).
How could I achieve such behaviour?
It looks like you could do this easily with the withLatestFrom operator like the following:
const a$ = ...;
const b$ = ...;
a$
.switchMap(v => Observable.of(v).delay(1000))
.withLatestFrom($b.startWith(null), (a, b) => b)
.subscribe(...);
I have this simple usecase that I can't seem to figure out.
Given 2 observables, A and B
A starts emitting items after B emits it's first item, and B can continue to emit items, which should no longer affect A.
I need this because A needs the first value emitted by B to start emitting.
I've tried both skipUntil and startWith to no avail.
I think flatMap can help you do what you want:
Observable<Integer> createA(Observable<Integer> B) {
return B.take(1).flatMap(b -> {
/* replace with your Observable A implementation here */
BehaviorSubject<Integer> subjectA = BehaviorSubject.create();
return subjectA;
});
}
This method returns an Observable A, which begins emitting only after it has been initialized with the first value emitted by Observable B.