0

I need to wait for some API call before letting page in my route to load. Basically we have A/B testing enabled (which is API call) and based on that will have to either load Component assosiated with that route or redirect to different url. To do that I was trying to use resolver that returns Observable<boolean>. Here is code:

export class RedirectResolveService implements Resolve<Observable<boolean>> {
  private empty = new Observable<boolean>();
  constructor(private apiService: ApiService, private router: Router) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> {
    return this.apiService.get("/api/abtest/mypage").pipe(
      tap((isOn) => {
        if (!isOn) {
          window.location.href = "/welcome-page";
        }
      }),
      first()
    );
  }
}

Then I add this in the route:

{
  path: 'new-page',
  component: NewPageComponent,
  resolve: {
    redirect: RedirectResolveService,
  },
},

And then in NewPageComponent I add subscription in the constructor:

export class NewPageComponent {
  constructor(private route: ActivatedRoute) {
    this.route.data.subscribe();
  }
}

It works but for the case when redirect happens I see first NewPageComponent rendered and then redirect happening. That makes sense since I subscribe to my Observable when Component initializes and thus only start redirect after that.

Is there way to make redirect logic without Component being initialized?

1
  • 2
    what if you used route guard instead of resolver ? Commented Aug 5, 2020 at 20:49

1 Answer 1

2

Using route guard it would be something like this

@Injectable({
  providedIn: "root",
})
export class RedirectGuard implements CanActivate {
  constructor(
    private _authService: AuthService,
    private _router: Router,
    private apiService: ApiService
  ) {}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree>
    | Promise<boolean | UrlTree>
    | boolean
    | UrlTree {
    return this.apiService.get("/api/abtest/mypage").pipe(
      tap(isOn => isOn || this._router.parseUrl("/welcome-page")),
      first()
    );
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! I was thinking about it but wasnt sure that canActivate method can return Observable

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.