Search code examples
angulartypescriptrxjsstreamreactive-programming

Angular/RxJS - There is a RxJS pipe for stream started?


Im trying to create a way to present and hide loading screen dinamically when resolving some stream.

Here is my current code:

this.requestService
        .get<Checkout>(`check/${orderNumber}`)
        .pipe(
            tap(() => this.startLoading()),  //i think this isnt the right way to use this pipe
            finalize(() => this.endLoading())
        )
        .subscribe(
            data => {
                data.orderNumber = orderNumber
                this.checkout.next(data)
            },
            error => {
                this.notification.warning(error)
            }
        )

The expected result is when my stream start, present loading screen with startLoading() end when operation is done, hide loading using endLoading().

My working code:

this.startLoading() //basically calling function before i create the stream

this.requestService
        .get<Checkout>(`check/${orderNumber}`)
        .pipe(                
            finalize(() => this.endLoading())
        )
        .subscribe(
            data => {
                data.orderNumber = orderNumber
                this.checkout.next(data)
            },
            error => {
                this.notification.warning(error)
            }
        )

Im using this tap pipe correctly? Is there another pipe to better resolve this?

What is the best way to do this using RxJS?


Solution

  • In your first example, your tap runs after your http request has completed.

    Ultimately, you would just call this.startLoading() before you start the http request.

    this.startLoading();
    this.requestService.get<Checkout>(`check/${orderNumber}`).pipe(
      finalize(() => this.endLoading())
    ).subscribe(() => {
    
    });
    

    If you really want to call this.startLoading() in a pipe you could call it before the http request starts by starting off with your own observable:

    return of(null).pipe(
      tap(() => this.startLoading()),
      concatMap(() => this.requestService.get<Checkout>(`check/${orderNumber}`)),
      finalize(() => this.endLoading())
    ).subscribe(() => {
    
    });
    
    

    But then there's not really much point in doing that.

    So your tap syntax is correct, it's just not executing when you think it should be.