Search code examples
javascriptrxjsrxjs-pipeable-operators

Looking for RxJs Operator that returns early, skipping operators below, not filter() or skip()


  • I have an autocomplete input.
  • Every time a letter is entered or deleted I do an HTTP request.
  • The response is mapped to a list of suggestions, which I show in a dropdown beneath the input.

However: If the last letter is deleted, making the input empty, I want to skip the HTTP request etc. and return an empty array instead.

So I need an operator called first in the pipe, which every time a condition is met skips all operators below and "returns early" just like a "break" or "return" statement in a for loop.

I cannot use filter(), because this operator would prevent the resulting observable to emit. But I need it to emit to clear the dropdown.

<input [formControl]="formGroup.searchTerm">
<ul>
 <li *ngFor="let suggestion of suggestions$ | async">{{suggestion}}</li>
</ul>
suggetions$ = this.formGroup.valueChanges.pipe(
    pluck('searchString')
    // filter(searchString => searchString.length > 0) // does not help
    unknownOperator(searchString => {
        if(searchString.length === 0) {
            skipOperatorsBelowAndReturnThisInstead([])
        } else {
            continueWithOperatorsBelow(searchTerm)
        }
    })
    switchMap(values => this.http.get(this.url + values.term)),
    map(this.buildSuggestions),
),

Thanks!


Solution

  • You can't skip all operators below with an operator. You have to switch to a different stream depending on a condition.

    suggetions$ = this.formGroup.valueChanges.pipe(
      pluck('searchString'),
      switchMap(searchString => searchString.length === 0
        ? of([])
        : this.http.get(this.url + searchString).pipe(
          map(this.buildSuggestions)
        )
      )
    );