[英]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.