Home > OS >  RxJS won't execute pipe operators after executing either first or find with a false predicate
RxJS won't execute pipe operators after executing either first or find with a false predicate

Time:03-29

I have this observable subscribtion

this.tooltipEventSubject.pipe(
    filter(event => event.type === "show"),
    tap(() => this.tooltipContent.loading = true),
    filter(() => this.messageContent?.sender !== undefined && this.tooltipContent.success === undefined),
    mergeMap(() => this.jabService.searchEntityInAddressBook(this.messageContent?.sender ?? "")),
    mergeMap(response => response.values),
    filter(response => response !== undefined) as OperatorFunction<Entity | undefined, Entity>,
    tap(() => console.log("before first")),
    find(entity => entity.name === this.messageContent?.sender),
    tap(() => console.log("after first")),
).subscribe({
    next: () => console.log("next"),
    error: err => console.log(err),
    complete: () => console.log("complete")
})

It hits the "find" predicate (checked with debugger) and then does nothing.

I have tried a lot of operators, like first following by a catchError, here on this example I have find.

It is getting to "before first", but then it won't print anything else. I am aware that the find predicate is returning false, and it should. But why does it stop running ? Shouldn't it return "undefined" to the following operators ? And shouldn't it even print "complete" ?

Thank you for your answers

CodePudding user response:

find operator will wait until predicate returns true and till then it will not emit any data even undefined.

find will emit undefined only when source observable completes and none of the data match.

In your case source observable is a form event,So it will not be completed unless you do.Ex.takeUntil ..

I am providing two example.

Ex. 1

from([1, 2, 3, 4]).pipe(
  tap((data) => console.log('Before find', data)),
  find((data) => data > 5),
  tap((data) => console.log('After find', data))
)
.subscribe({
  next: console.log,
  error: console.error,
  complete: () => console.log('Completed'),
});

Output:

Before find 1

Before find 2

Before find 3

Before find 4

After find undefined

undefined

Completed

Ex. 2

<button id="btnFind">Find</button>
const btnFind = document.getElementById('btnFind');
let count: number = 0;
fromEvent(btnFind, 'click')
  .pipe(
    tap(() => count  ),
    // takeUntil(timer(5000)),
    tap((count) => console.log('Before find', count)),
    find(() => count > 4),
    tap((count) => console.log('After find', count))
  )
  .subscribe({
    next: (e) => console.log(e),
    error: console.error,
    complete: () => console.log('Completed'),
  });

In 2nd example It will emit after 5th click or if you uncomment takeUntil then after 5 seconds

CodePudding user response:

If your predicate returns false that means there's no value that matches your condition and the 'find' operator simply will not return any value in this case.

check official rxjs doc for more: https://rxjs.dev/api/operators/find

  • Related