在我的应用程序中,我使用第三方身份验证来登录用户,然后在其本地存储中设置令牌。我正在编写一个服务来缓存配置文件信息,它接受该用户的auth令牌并调用一个getUser()后端方法来返回用户配置文件信息。
问题是,在localstorage中设置令牌的时间与应用程序依赖令牌在初始化时进行后端调用的时间之间存在轻微延迟。

export class UserService {
  private userProfileSubject = new BehaviorSubject<Enduser>(new Enduser());
  userProfile$ = this.userProfileSubject.asObservable();

  constructor(
    private _adService: AdService,
    private _authService: AuthnService) { }

  setUserProfile() {
    const username = this._authService.getUser();
    this.userProfile$ = this._adService.getUser(username).pipe(
      first(),
      map(result => result[0]),
      publishReplay(1),
      refCount()
    );
    return this.userProfile$;
  }
}

这是检查localstorage令牌并返回用户名的同步方法。
public getUser(): string {
    const jwtHelper = new JwtHelperService()

    const token = localStorage.getItem(environment.JWT_TOKEN_NAME);
    if (!token || jwtHelper.isTokenExpired(token)) {
      return null;
    } else {
      const t = jwtHelper.decodeToken(token);
      return t.username;
    }
  }

因此,需要先完成this._authService.getUser();才能在this._adService.getUser(username)中使用它。
我想这样做的方法是让getUser()方法返回一个可观察的takeWhile,直到值!== null。或者使用timer。试了几个小时都没有成功。
任何帮助都非常感谢。
γ
编辑:
这似乎很有效,但使用timer让我觉得很麻烦,我宁愿用另一种方式:
user.service.ts
  setUserProfile() {
    timer(100).pipe(
      concatMap(() => {
        const username = this._authService.getUser();
        return this._adService.getUser(username)
      }),
      map(res => res[0])
    ).subscribe(profile => {
      this.userProfileSubject.next(profile);
    });
  }

app.component.ts ngOnInit
this._userService.setUserProfile();
    this._userService.userProfile$.pipe(
      map((user: Enduser) => this._userService.setUserPermissions(user)),
      takeUntil(this.ngUnsubscribe)
    ).subscribe();

编辑2:工作解决方案
isLoggedIn()是设置本地存储的方法。在这里,我正在等待设置它,然后继续获取用户配置文件信息。
this._authService.isLoggedIn().pipe(
      concatMap(() => {
        const username = this._authService.getUser();
        return this._adService.getUser(username)
      }),
      map(res => res[0])
    ).subscribe(profile => {
      this.userProfileSubject.next(profile);
    });
  }

IsLogGeDin:
isLoggedIn(state): Observable<boolean> {

    ...

    return this.http.get(url, {withCredentials: true}).pipe(
      map((res: any) => {
        const token = res.mdoc.token;

        if (token) {
          localStorage.setItem(environment.JWT_TOKEN_NAME, token);
          return true;
        } else {
          return false;
        }
      })
  }

最佳答案

如我在评论中所述,您希望等待this._authService.getUser()完成的问题没有意义,因为如果this._authService.getUser()是同步的(如您所述),那么它将始终在执行下一行代码之前完成。
不管怎样,读完你的代码我想我知道你想做什么…
获取用户名表单this._authService.getUser()
将用户名传递给this._adService.getUser()
等待this._adService.getUser()完成并将其值传递给可观测流,userProfile$
为了实现这一点,您不需要那些花哨的rxjs操作符;您的代码可以简单到:

export class UserService {
  private userProfileSubject = new BehaviorSubject<Enduser>(new Enduser());
  userProfile$ = this.userProfileSubject.asObservable();

  constructor(
    private _adService: AdService,
    private _authService: AuthnService
  ) {}

  setUserProfile() {
    const username = this._authService.getUser();

    this._adService.getUser(username).subscribe((userProfile: Enduser) => {
      this.userProfileSubject.next(userProfile);
    });
  }
}

正如我在上面所做的,只要发送到userProfile$流,然后在你的应用程序中任何想要获取用户配置文件数据的地方订阅它。
现在,您可以在应用程序的任何位置执行此操作,以便在用户配置文件数据沿流发送时获取该数据:
constructor(private _userService: UserService) {
  _userService.userProfile$.subscribe((userProfile: Enduser) => {
    console.log(userProfile);
  });
}

关于angular - Angular 6-如何在服务中使用Observable来等待直到Okta token 存在于本地存储中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51664591/

10-09 18:34