如何从返回Observable的Promise中返回Observable?代码实现咨询
Hey there! Let's break down what's going wrong in your current code and fix it to get the clean Observable<boolean> output you need.
The Issue with Your Current Implementation
Right now, your fromPromise is wrapping a Promise that resolves to another Observable (the one returned by this.fetchUserData().pipe(...)). That means your function ends up returning an Observable<Observable<boolean>> instead of the flat Observable<boolean> you're aiming for. We need to flatten this nested structure properly using RxJS operators.
The Corrected Approach
Instead of mixing Promise .then()/.catch() with Observable logic, we can convert the initial Promise to an Observable and use RxJS's switchMap to handle the transition to the second Observable. This keeps everything in a clean, unified Observable chain:
import { from, Observable } from 'rxjs'; import { switchMap, map, catchError } from 'rxjs/operators'; public isAuthenticated(): Observable<boolean> { // Convert the renewTokens Promise to an Observable (RxJS 6+ prefers `from()` over `fromPromise`) return from(this.renewTokens()).pipe( // Switch to the fetchUserData Observable once renewTokens succeeds switchMap(() => this.fetchUserData()), // Map the user result to a boolean: true if user exists, false otherwise map(user => { // Store your user object in your desired location here return user !== null; }), // Handle errors from either renewTokens or fetchUserData catchError(error => { this.ctx.log.error('Authentication error', error); // Return an Observable that emits false to indicate unauthenticated state return from([false]); }) ); }
Key Improvements Explained
from()instead offromPromise: RxJS 6+ recommendsfrom()for converting Promises (and iterables) to Observables—it's more versatile and future-proof.switchMap: This operator takes the resolved value from therenewTokensObservable, then switches to thefetchUserDataObservable. It automatically flattens the nested stream, so you get a directObservable<boolean>output.- Unified Error Handling: Using
catchErrorat the end of the pipeline catches errors from bothrenewTokensandfetchUserData, keeping all error logic in one consistent place. - Clean Observable Chain: Everything stays within the RxJS pipeline, avoiding messy Promise-Observable nesting that's hard to maintain.
Why Your Original Code Failed
When you used fromPromise(this.renewTokens().then(() => fetchUserDataObs)), the outer Promise resolves to an Observable. This means the outer Observable emits that inner Observable—you'd have to subscribe twice to get the boolean value, which isn't what you want. switchMap fixes this by subscribing to the inner Observable for you and passing its emissions directly through to the outer stream.
内容的提问来源于stack exchange,提问作者Sammy

