Lindauson
Lindauson

Reputation: 3461

How can I access original observable value in tap after map?

I am building an Angular 6 guard. After the boolean is calculated by the map operator, I would like the original value of user available in the tap operator to calculate the redirect.

return this.auth.user$.pipe(
    take(1),
    // Existing Users cannot register
    map(user => user ? false : true),
    tap(canAccess => {
        if (!canAccess) {
            // Calculate route based on user value
        }
    })
);

I am very new to RxJS. Is there a way to access the original user value in the tap operator without creating a duplicate user observable?

(I guess I could technically tap before the map, but it seems odd to redirect before transforming the value.)

Upvotes: 0

Views: 1396

Answers (2)

Jeto
Jeto

Reputation: 14927

You could use map, tap and then map again. The last map allows you to end up with an Observable<boolean>, which I suppose you require in the end.

  • map(user => [user, !user]) maps the original value to an array of two values: the user and their access flag (boolean)
  • tap([user, canAccess]) => { ... } takes both values and does the computations you need on the user depending on the flag
  • map(([user, canAccess]) => canAccess) takes both values and return the one you need in the end (the boolean flag)

This way you don't have to duplicate your canAccess condition.

return this.auth.user$.pipe(
  take(1),
  map(user => [user, !user]),   // !user should be equivalent to user ? false : true
  tap(([user, canAccess]) => {
    if (!canAccess) {
      // Calculate route based on user value
    }
  }),
  map(([user, canAccess]) => canAccess)
);

Upvotes: 2

SiddAjmera
SiddAjmera

Reputation: 39482

Doing what you're doing right now will transform the user to a boolean. So in that next tap, you'll eventually get a boolean.

Why don't you use the user directly in the tap and get rid of that map?

If user is defined, if(!user) will resolve to false anyway.

And if user is undefined or null, then if(!user) will resolve to true.

And yeah, as you said, since you need to return an Observable<boolean>, you'll have to map it to a boolean

So you can use this:

return this.auth.user$.pipe(
    take(1),
    tap(user => {
        if (!user) {
            // Calculate route based on user value
        }
    }),
    map(user => user ? false : true)
);

Upvotes: 2

Related Questions