Хаха, ReactiveX не из легких.У него довольно крутая кривая обучения.Но это действительно мощно.
1.вызвать сервер только один раз
Вы можете использовать shareReplay.
Чтобы понять, как работает shareReplay, посмотрите здесь https://ng -rxjs-share-replay.stackblitz.io
//shareReplay example
ngOnInit() {
const tods$ = this.getTodos();
tods$.subscribe(console.log);// 1st sub
tods$.subscribe(console.log);// 2st sub
}
getTodos(): Observable<Todo[]> {
return this.http.get<Todo[]>(this.url)
.pipe(
tap(() => console.log('Request')),
shareReplay(1) // compare with comment and uncomment
);
}
Вывод с помощью shareReplay
Request
[Object, Object, Object]
[Object, Object, Object]
Вывод без shareReplay
Request
[Object, Object, Object]
Request
[Object, Object, Object]
Вы можете использовать shareReplay в своем сервисном коде аутентификации.
//auth.services.ts
import { shareReplay } from 'rxjs/operators';
...
this.user$ = this.afAuth.authState.pipe(
tap(user => {
console.log('login user$ here', user)
}),
switchMap(user => {
if (user) {
//do something
return this.db.object(`users/${user.uid}`).valueChanges();
} else {
return of(null);
}
}),
shareReplay(1) //**** this will prevent unnecessary request****
);
2.асинхронно и жду toPromise()
//auth.service.ts
...
getUser() {
return this.user$.pipe(first()).toPromise();
}
//auth.guard.ts
...
async canActivate(next: ActivatedRouteSnapshot
, state: RouterStateSnapshot
): Promise<boolean> {
const user = await this.auth.getUser();
//TODO your API code or other conditional authentication here
if (!user) {
this.router.navigate(['/login']);
}
return !!user;
}
Надеюсь, это поможет вам.