Angular 路由 - 在每次路由更改时获取用户数据

问题描述 投票:0回答:1

我在使用 Angular Guards 从 API 获取用户信息时遇到问题。我的目标是在本地存储中始终保留最新的用户数据。我想确保每当路线发生变化时都能从 API 获取最新数据。

为了实现这一目标,我一直在使用守卫来调用 API 并获取用户信息。然而,问题在于,当在守卫内调用 API 时,会导致打开页面(路由)出现延迟,因为守卫会等待 API 响应才能继续操作。因为我创建了一个函数顺序守卫,它按顺序处理每个守卫,而不是异步处理,正如您在路线中看到的那样,我的一条路线有多个守卫,并且在继续其他路线之前我需要来自用户 API 的新数据。

我不太喜欢这种方法,因为它在页面导航中引入了不必要的等待时间。所以,我想知道是否有更好的解决方案,可以在不等待API响应的情况下更改路由,并且可以在后台异步获取用户数据,但之后它将传递来自守卫的逻辑或将其从页面踢出- 因为守卫是为了保护用户不访问基于其自身属性的页面,例如如果用户未登录,则他无法访问 /home 页面等。

sequentialGuards()

export function sequentialGuards(guards: CanActivateFn[]): CanActivateFn {
    return (route, state) => {
        const injectionContext = inject(Injector);
        // Convert an array into an observable.
        return from(guards).pipe(
            // For each guard, fire canActivate and wait for it to complete.
            concatMap((guard) => {
                return runInInjectionContext(injectionContext, () => {
                    var guardResult = guard(route, state);
                    if (guardResult instanceof Observable) {
                        return guardResult;
                    } else if (guardResult instanceof Promise) {
                        return from(guardResult);
                    } else {
                        return of(guardResult);
                    }
                });
            }),
            // Don't execute the next guard if the current guard's result is not true.
            takeWhile((value) => value === true, true),
            // Return the last guard's result.
            last()
        );
    };
}

路线

{
                path: 'home',
                component: HomeComponent,
                canActivate: [sequentialGuards([authGuard, verifyGuard, onboardGuard])],
            },
            {
                path: 'documents',
                component: DocumentsComponent,
                canActivate: [sequentialGuards([authGuard, verifyGuard, onboardGuard])],
            },

authGuard

export const authGuard: CanActivateFn = (route, state) => {
    const url: string = decodeURIComponent(state.url);
    return inject(CheckLoginService).checkLogin(url);
};

检查登录服务

export class CheckLoginService {
    constructor(private authService: AuthService,
                private tokenService: TokenService,
                private userService: UserService,
                private router: Router) {
    }

    checkLogin(url: string): Observable<boolean> {
        return this.authService.user().pipe(
            switchMap(() => {
                if (this.tokenService.getToken() && this.userService.getUser()) {
                    return of(true);
                }

                this.authService.redirectUrl = url;
                this.router.navigate(['/login'], {queryParams: {returnUrl: url}});
                return of(false);
            }),
            catchError(() => {
                this.authService.redirectUrl = url;
                this.router.navigate(['/login'], {queryParams: {returnUrl: url}});
                return of(false);
            })
        );
    }
}
angular routes
1个回答
0
投票

在根组件中,在每个

NavigationEnd
上触发 API 调用。

ngOnInit() {
  this.firstChildData$ = this.router.events.pipe(
    filter((e): e is NavigationEnd => e instanceof NavigationEnd),
    map(e => {
      // make the API call here
    })
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.