Home > Enterprise >  delayUntil stop delay and emit next value if notification is closed
delayUntil stop delay and emit next value if notification is closed

Time:07-16

I need to create a toaster.

I have the Subject

this.toast$ = this.toastSubject.asObservable().pipe(
  filter(toast => toast !== null),
  concatMap((toast) => of(toast).pipe(delayWhen(() => timer(5000)), skip(1), startWith(toast)))
);

The show toaster method

show(type: ToastType, title: string, body: string, delay?: number): void {
  this.toastSubject.next({ type, title, body, delay: delay || undefined, showIcon: true });
}

I'm subscribing inside the component and pushing inside the array the toaster notifications. So by using concatMap and delay it waits for the observable to finish and then emits another one that lasts 5 seconds.

My issue:

If i close the notification after 1 second, and the delay is 5 seconds, i still have to wait 4 seconds for the 2nd notification.

I've made another observable to listen to the closing event of the notification but how can i stop the delay and emit the next value immediately??

I've tried with takeUntil.

I've even tried a custom delayUntil

 export function delayUntil<T>(
   notifier: Observable<SafeAny>
 ): OperatorFunction<T, T> {
   return (source) =>
     source.pipe(
       publish((published) => {
         const delayed = new Observable<T>((subscriber) => {
           let buffering = true;
           const buffer: T[] = [];
           const subscription = new Subscription();
           subscription.add(
             notifier.subscribe(
               () => {
                 buffer.forEach((value) => subscriber.next(value));
                 subscriber.complete();
               },
               (error) => subscriber.error(error),
               () => {
                 buffering = false;
                 buffer.length = 0;
               }
             )
           );
           subscription.add(() => {
             buffer.length = 0;
           });
           subscription.add(
             published.subscribe(
               (value) => buffering && buffer.push(value),
               (error) => subscriber.error(error)
             )
           );
           return subscription;
         });
         return concat(delayed, published);
       })
     );
 }

It still doens't work.

StackBlitz

Thank you !

CodePudding user response:

race is probably what you are looking for !

this.toast$ = this.toastSubject.pipe(
  concatMap((toast) =>
    of(toast).pipe(
      delayWhen(() => race([this.toastClose$, timer(5000)])),
      skip(1),
      startWith(toast)
    )
  )
);

Stackblitz

  • Related