RxJS takeWhile but include the last value
UPDATE March 2019, rsjx
version 6.4.0
: takeWhile
finally have an optional inclusive
parameter that allows to keep the first element that breaks the condition. So now the solution would be simply to pass true as the second argument of takeWhile
:
import { takeWhile } from 'rxjs/operators';
import { from } from 'rxjs';
const cutOff = 4.5
const example = from([2, 3, 4, 5, 6])
.pipe(takeWhile(v => v < cutOff, true ))
const subscribe = example.subscribe(val =>
console.log('inclusive:', val)
);
outputs:
inclusive: 2
inclusive: 3
inclusive: 4
inclusive: 5
Live here:
https://stackblitz.com/edit/typescript-m7zjkr?embed=1&file=index.ts
Notice that 5 is the first element that breaks the condition. Notice that endWith
is not really a solution when you have dynamical conditions like v < cutOff
and you don't know what will be your last element.
Thanks @martin for pointing out the existence of this pull request.
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
You can use endWith(value)
which (unlike a lot of RxJS code)
is very nicely self documenting.
const example = source.pipe(
takeWhile(val => val != 4),
endWith(4));
PS. Also note that takeUntil
doesn't take a predicate, so if you were trying to use that operator to solve this problem you can't. It's a whole different method signature.
Official docs: https://rxjs-dev.firebaseapp.com/api/operators/endWith
https://stackblitz.com/edit/typescript-pvuawt