I’m trying to determine how/if I can convert a Promise rejection into a typed Observable.
I have a login component with a function like this…
login() { const login$ = this.authenticationService.login(this.loginForm.value) login$ .pipe( finalize(() => { this.loginForm.markAsPristine(); this.isLoading = false; }), untilDestroyed(this) ) .subscribe( (credentials) => { log.debug(`${credentials.username} successfully logged in`); this.router.navigate([this.route.snapshot.queryParams.redirect || '/'], { replaceUrl: true }); }, (error) => { log.debug(`Login error: ${error}`); this.error = error; } ) }
and an authentication service with a method like this…
login(context: LoginContext): Observable<Credentials> { var data = {} as Credentials // Call a method that returns a Promise this.server.authenticate(LoginContext) .then((result) -> { data.username = result.user.username data.token = result.accessToken this.credentialsService.setCredentials(data, context.remember) // Not sure what to do here...need to return data somehow as an Observable // return data }) .catch((err) => { // Not sure what to do here either...need to bubble the err up so that it's caught in subscribe // return throwError(err) }) }
How can I return an Observable<Credentials>
if the Promise resolves, and bubble up the error if it rejects?
I know I can make everything work if I change the authentication service function to return Promise<Observable<Credentials>>
, which is fine, but for the sake of learning new things I’m trying to figure out if this is possible.
Advertisement
Answer
You can use the from
function to convert any Promise
to an Observable
:
import { from } from 'rxjs'; // ... class YourClass { login(context: LoginContext): Observable<Credentials> { return from(this.server.authenticate(LoginContext).then(result => { const credentials: Credentials = { username: result.user.username, token: result.accessToken }; this.credentialsService.setCredentials(credentials, context.remember); return credentials; })); } }