Angular 9:为什么 Subject 没有在 tap 运算符内触发?

Angular9: why is the Subject not firing inside the tap operator?

我的登录函数中有一个点击运算符,我在其中触发 Subject 并在 localStortage 中保存一些内容。变量保存在 localStorage 中,但 Subject 不会触发。

    login({ username, password }: any): Observable<any> {
    return from(
      this.afAuth.auth.signInWithEmailAndPassword(username, password)
    ).pipe(
      tap((resData) => {
        const uid: string = resData.user.uid;
        this.loggedInUser.next(uid);
        localStorage.setItem('lu', JSON.stringify(uid));
      })
    );
}

我正在另一个组件中订阅它,但那里没有任何反应:

this.authenticationService.loggedInUser.
     subscribe(user => console.log(user)) //nothing happens here
   
 

问题出在哪里?我是不是操作员做错了什么?

您何时何地订阅 login 功能?

你需要有这样的东西才能激发你的逻辑。

const userPwd = { username: 'MyName', password: 'MyPwd' };
login(userPwd).subscribe(
  next: resp => {
    // do something with the response
  },
  err => {
    // handle error
  },
  () => {
    // do something when the Observable completes; probably nothing since it looks like an Observable which emits just once
  }
)

此外,您可能不需要在此处使用 Subject。你可以有这样的东西

login({ username, password }) {
    return from(
      this.afAuth.auth.signInWithEmailAndPassword(username, password)
    ).pipe(
      map((resData) => { // instead of firing a Subject within a tap operator you use map and return the uid 
        const uid = resData.user.uid;
        localStorage.setItem('lu', JSON.stringify(uid));
        return uid
      })
    );
}

const userPwd = { username: 'MyName', password: 'MyPwd' };
this.authenticationService.logIn(userPwd).
     subscribe(user => console.log(user)) //something should happen here

如果login在两个不同的组件中订阅,您可能需要共享订阅(即只调用一次远程授权服务)并且您可能会遇到时间问题。

假设 login 首先由组件 C1 订阅,然后由组件 C2 订阅,并且您想要调用 this.afAuth.auth.signInWithEmailAndPassword(username, password) 只需一次并在 C1C2 之间共享结果。

在这种情况下,您可以使用运算符 shareReplay 来实现您的目标,如此处

login({ username, password }) {
    return from(
      this.afAuth.auth.signInWithEmailAndPassword(username, password)
    ).pipe(
      map((resData) => { // instead of firing a Subject within a tap operator you use map and return the uid 
        const uid = resData.user.uid;
        localStorage.setItem('lu', JSON.stringify(uid));
        return uid
      }),
      shareReplay(1). // 1 means that only the last value is cached and repalyed
    );
}