I have a RxJS5 pipeline looks like this
Rx.Observable.from([2, 3, 4, 5, 6])
.takeWhile((v) => { v !== 4 })
I want to keep the subscription until I see 4, but I want to last element 4 also to be included in the result. So the example above should be
2, 3, 4
However, according to official document, takeWhile
operator is not inclusive. Which means when it encounters the element which doesn't match predicate we gave, it completes the stream immediately without the last element. As a result, the above code will actually output
2, 3
So my question is, what's the easiest way I can achieve takeWhile
but also emit the last element with RxJS?
Since RxJS 6.4.0 this is now possible with takeWhile(predicate, true)
.
There's already an opened PR that adds an optional inclusive
parameter to takeWhile
: https://github.com/ReactiveX/rxjs/pull/4115
There're at least two possible workarounds:
using concatMap()
:
of('red', 'blue', 'green', 'orange').pipe(
concatMap(color => {
if (color === 'green') {
return of(color, null);
}
return of(color);
}),
takeWhile(color => color),
)
Using multicast()
:
of('red', 'blue', 'green', 'orange').pipe(
multicast(
() => new ReplaySubject(1),
subject => subject.pipe(
takeWhile((c) => c !== 'green'),
concat(subject.take(1),
)
),
)
I've been using this operator as well so I made it to my own set of additional RxJS 5 operators: https://github.com/martinsik/rxjs-extra#takewhileinclusive
This operator has been also discussed in this RxJS 5 issue: https://github.com/ReactiveX/rxjs/issues/2420
Jan 2019: Updated for RxJS 6