1

Consider the following sample:

I have a non completing rxjs Observable providing me with an array of numbers (e.g. of([1, 2, 3, 4, 5])) and a custom filter function that returns an Observable boolean (also non completing) for each number (signifying whether the number should be included in the result or not).

My question: What is the best combination of operators to apply this filter?

Note: A solution using toArray (like described in RxJs: Filter array with inner observable) won't work for me: The observables returned by my filter function never complete and for obvious reasons toArray can only work with streams that do.

What I came up with so far is this monster using the scan operator: https://stackblitz.com/edit/from-and-back-to-array?devtoolsheight=133&file=index.ts

I believe it works, but I can't help thinking that there must be an easier way to accomplish this. 🤔 Anyone have an idea?

2
  • Can you be more specific what are you trying to do? I don't know what's a non completing filter function returning Observable or what the stackblitz code suppsoed to do. Commented Nov 26, 2020 at 11:54
  • Yeah I'll try to rephrase my question a bit, but it is a complicated setting. By "non completing Observable" I mean an Observable that never calls complete() internally. (For example interval(100) creates such an Observable for testing. Commented Nov 26, 2020 at 12:29

1 Answer 1

1

I think this should work.

const filtered$ = remoteSource$.pipe(
  // if new source values come in, switch to those and discard the current values
  switchMap(nums => {
    // an array of observables each emitting a number if it passes the filter or else undefined
    const checkedNumbers = nums.map(num => numFilter$(num).pipe(
      map(isValid => isValid ? num : undefined)
    ));
    // combine those observables
    return combineLatest(checkedNumbers);
  }),
  // filter out undefined values, i.e. numbers that didn't pass the filter above
  map(checkedNumers => checkedNumers.filter(num => num !== undefined)),
);

https://stackblitz.com/edit/from-and-back-to-array-6slvvf?file=index.ts

Sign up to request clarification or add additional context in comments.

3 Comments

Wow - that was fast! Thanks a lot. I hadn't though about switchMap in this setting.
I found just one small issue but that actually wasn't something I explained in my question: I also need the filter to emit when there are no values in the Observable array (remoteSource$). I just had to add a if (nums.length === 0) { return of([]); } at the top of the switchMap.
prefer not define something as undefined. I think null is better (please correct me if I'm wrong). And then filter by simply doing !!num instead of the num !== undefined (or just use the lodash compact). Using the array.filter can still think the type contains undefined but compact is typed correctly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.