簡體   English   中英

如何避免在 promise 中返回 observable

[英]How to avoid to return an observable inside a promise

我正在使用AngularFire來管理我的應用程序中的用戶。 我還在學習 observables 和 rxjs。

我正在嘗試調用signInWithEmailAndPassword方法 - 它返回 promise - 並從集合中檢索文檔。

在我的服務中,我使用以下方法獲取文檔:

 getDbUser(uid): Observable<User> { return this.angularFirestore.collection<User>(USERS).doc(uid).valueChanges() }

我登錄用戶:

 login(user: User) { // sign in con email e password return this.angularFireAuth.signInWithEmailAndPassword(user.email, user.password).then((result) => { if(result.user?.uid) { // get user doc return this.getDbUser(result.user.uid); } return null; }); }

使用此代碼,調用登錄方法需要解決一個 promise 然后訂閱 observable,如下所示:

 this.userService.login(this.loginUser).then((userObs) => { userObs.subscribe((user) => { console.log(user); }); })

我真的很想避免這種情況,但我不知道該怎么做。 我嘗試使用 RxJs toPromise運算符:

 login(user: User) { // sign in con email e password return this.angularFireAuth.signInWithEmailAndPassword(user.email, user.password).then((result) => { if(result.user?.uid) { // recupero l'utente dal db return this.getDbUser(result.user.uid).toPromise(); } return null; }); }

但不知何故,這不起作用(promise 從未解決)。

toPromise()不起作用的原因是 observable 保持打開狀態。 使用第一個運算符,或者如果您使用的是更高版本的 rxjs, firstValueFrom 閱讀 rxjs 文檔中的Promises 轉換以了解更多信息。

由於您使用valuesChanges而不是get ,那么您的意圖可能是保持可觀察的開放。 如果是這種情況,那么最好的辦法是使用from將登錄轉換為可觀察的。

login(user: User) {
  return from(this.angularFireAuth.signInWithEmailAndPassword(user.email, user.password)).pipe(
    switchMap(res => (res.user.uid) 
      ? this.getDbuser(res.user.uid)
      : of(null))
  );
}

嘗試使用 rxjs 運算符,例如 mergeMap、swtichMap、pipe、map 等。您可以避免使用這些運算符進行嵌套訂閱。

如果您想讓任何可觀察的消費者知道用戶僅在 signInWithEmailAndPassword() 已返回后才登錄,我將貼上主題並從任何服務消費者訂閱 user$。

private userSubject$:Subject<string>=new Subject<string>();
public user$:Observable<string>=this.userSubject$.asObservable();
    login(user: User) {

    // sign in con email e password
    return this.angularFireAuth.signInWithEmailAndPassword(user.email, user.password)
      .then((result) => {

        if(result.user?.uid) {

          // recupero l'utente dal db
          return this.userSubject$.next(result.user.uid);
        }

        return null;
      });

並且從外部您將使用該服務:

this.userService.login(this.loginUser);
this.userService.user$.subscribe(user=>console.log);

第一條評論是正確答案:

您可以在 .toPromise 之前添加.toPromise .pipe(first())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM