RxJS skipWhile vs filter
Asked Answered
A

4

44

What is the difference between skipWhile and filter operators?

const source = interval(1000);
const example = source.pipe(skipWhile(val => val < 5));
const subscribe = example.subscribe(val => console.log(val));


const source = interval(1000);
const example = source.pipe(filter(val => val > 5));
const subscribe = example.subscribe(val => console.log(val));
Ahab answered 22/3, 2018 at 7:59 Comment(0)
J
71

The difference is that upon its expression evaluating to false, skipWhile changes over to mirroring its source observable - so it will cease to filter out any further values.

For example:

Observable.from([1,2,3,4,5])
  .pipe(filter(val => val % 2 == 0)) // filters out odd numbers
  .subscribe(val => console.log(val)); // emits 2,4

Observable.from([1,2,3,4,5])
  .pipe(skipWhile(val => val % 2 == 1)) // filters odd numbers until an even number comes along
  .subscribe(val => console.log(val)); // emits 2,3,4,5
Japeth answered 22/3, 2018 at 8:8 Comment(6)
I'm sorry, I can't fully understand it. Can you please make it more clear? maybe with another example? thanks.Ahab
@Ahab skipWhile will only start emitting all next values when the condition for the first time evaluates to false. filter will always filter every emitted value which does not conform to the given filter condition.Russianize
So skipWhile is a one-time filter.Ahab
skipWhile is a waste of time that makes developers angry - filter is what you want :DGladi
@Gladi But it can be very useful to wait for a Observable be the first time connected, like for a connection to a websocketEtna
The operator should be definitely called skipUntil as this much better describes what it doesRemorseful
K
15
Observable.from(["Citizen 1","Citizen 2","President","Citizen 3","Citizen 4"])
  .pipe(filter(val => val == "President")) // Only let the president into the bunker.
  .subscribe(val => console.log(val)); // emits President

Observable.from(["Citizen 1","Citizen 2","President", "Citizen 3","Citizen 4"])
  .pipe(skipWhile(val => val != "President")) // Let the citizens enter the bunker, but only after the president enters.
  .subscribe(val => console.log(val)); // emits President, Citizen 3, Citizen 4
Kimbra answered 15/10, 2019 at 7:52 Comment(0)
Q
5

skipWhile operator will ignore the emissions until the specified condition becomes false, but after that, it will continue to take values from the source observable as is.

const randomNumbersLessThanEqualToTen = interval(1000).pipe(map((num) => {
    const randomNumber = Math.floor(Math.random()*num);
    console.log('Random Number Generated', randomNumber);
    return randomNumber;
}), skipWhile(num => num < 10));

randomNumbersLessThanEqualToTen.subscribe((number) => {
    console.log('Number not skipped', number);
});

o/p

Random Number Generated 6
Random Number Generated 0
Random Number Generated 5
Random Number Generated 0
Random Number Generated 5
Random Number Generated 11
Number not skipped 11
Random Number Generated 6

As soon as 11 (i.e. num < 10 === false) got generated and emitted all the generated numbers were taken and printed.

Here is an example of filter:

const randomNumbers = interval(1000).pipe(map((num) => {
    const randomNumber = Math.floor(Math.random() * num);
    console.log('Random Number Generated', randomNumber);
    return randomNumber;
}), filter(num => num > 10));
randomNumbers.subscribe((number) => {
    console.log('Number is greater than 10 -->', number);
});

o/p

Random Number Generated 7
Random Number Generated 11
Number is greater than 10 --> 11
Random Number Generated 13
Number is greater than 10 --> 13
Random Number Generated 13
Number is greater than 10 --> 13
Random Number Generated 3
Random Number Generated 2

So above output simply showcased that filter simply filters the emissions on the basis of the condition specified and it filters throughout the lifetime of observable.

Quadriplegia answered 31/10, 2020 at 5:46 Comment(0)
L
0

Working Example

skipWhile will start emitting values when the condition becomes false for the first time (after which the condition will be ignored and all vales will be emited). In your (slightly modified) example below, after the first emission of values >=5, all subsequent values are emitted (so we can see passed numbers less than 5).

const { interval } = rxjs;
const { skipWhile, map, tap } = rxjs.operators;

const source = interval(1000).pipe(map(x => x%10 ), tap(x => console.log('emited: ',x) )) // gen numbers in range 0-9
const example = source.pipe(skipWhile(val => val < 5));
const subscribe = example.subscribe(val => console.log('         '+val+' passed'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>

filter will emit only those values for which the condition is met. In your (modified) example below, only values >5 are emitted (we not see passed numbers <=5).

const { interval } = rxjs;
const { filter, map, tap } = rxjs.operators;

const source = interval(1000).pipe(map(x => x%10 ), tap(x => console.log('emited: ',x) ))
const example = source.pipe(filter(val => val > 5));
const subscribe = example.subscribe(val => console.log('         '+val+' passed'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>
Lal answered 8/5, 2024 at 17:0 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.