CuriousGeorge
CuriousGeorge

Reputation: 569

Triggering side effects when a value is filtered using filter() operator

I'm working on a username search input that fires after a debounceTime(). I also filter out values. I want to trigger some side effects if values are filtered (such as setting an error message and stopping loaders).

I'm achieving this right now by using tap() and checking the same predicate that I later check in a filter() function. I feel this is bad/there is a more proper way to achieve this.

private setUserSearchObservable() {
    this.userSearch = userSearch$.pipe(
      tap(() => this.loading = true),
      debounceTime(500),
      this.filterValuesWithErrorMessages(),
      ......
    );
}

private filterValuesWithErrorMessages() {
    return pipe(
      tap((val: string) => { if (this.usernamesMatch(val)) { this.errorMessage = 'You will be added to the frame automatically'; this.loading = false; }}),
      tap((val: string) => { if (this.usernameInArray(val)) { this.errorMessage = 'User is already added'; this.loading = false; }}),
      tap((val: string) => { if (val.length < 2) { this.errorMessage = ''; this.loading = false; }}),
      filter((val: string) => (val.length >= 2 && !this.usernamesMatch(val) && !this.usernameInArray(val))),
    );
}

As you can see, I explicitly check the exact same conditionals using tap() right before using them on filter(). Is there an operator/different pattern that will allow me to achieve this in a more concise way?

Upvotes: 0

Views: 832

Answers (1)

Fan Cheung
Fan Cheung

Reputation: 11370

Refactored your code a little bit, there is no specific operator to deal with error checking, you can use switchMap and inner observable e.g of, never to control whether the result should go through.

private setUserSearchObservable() {
    this.userSearch = userSearch$.pipe(
      tap(() => this.loading = true),
      debounceTime(500),
      map((value) => this.filterValuesWithErrorMessages(value)),
      swtichMap(msg => {
        if (msg !== false) {
          this.errorMessage = result
          this.loading = false
          return never()
        }
        return of(true)
      })
    );
  }

  private filterValuesWithErrorMessages(val) {
    if (this.usernamesMatch(val)) return 'You will be added to the frame automatically'
    if (this.usernameInArray(val)) return 'User is already added'
    if (val.length < 2) return ''
    return false
  }

Upvotes: 2

Related Questions