Search code examples
rxjsreactive-programming

Show a success message for a short period (without a race condition) in Rxjs


A button gets clicked, performs an action, and a success message gets shown briefly, based on the boolean values in the stream.

let copied: Observable<boolean> = fromEvent(button, "click").pipe(
  mergeMap(() => navigator.clipboard.writeText(...)), // writeText returns a promise
  switchMap(() => [of(true), of(false).pipe(delay(1000))]),
  startWith(false),
);

Obviously this doesn't work, as I've got Observables in switchMap, not values.

We need false -> Click -> perform action -> true -> delay -> false

Note, if the button is quickly clicked again, the message shouldn't disappear (hoping to solve the obvious race condition).


Solution

  • Your code is close. Instead of returning an array inside your switchMap, return an observable that emits the two values you want. You can use concat to create a single observable from your two sources of(true) and of(false).pipe(delay(1000)):

    const copied: Observable<boolean> = fromEvent(button, 'click').pipe(
      mergeMap(() => navigator.clipboard.writeText('')),
      switchMap(() => concat(of(true), of(false).pipe(delay(1000)))),
      startWith(false),
    );