Akxe
Akxe

Reputation: 11535

Merge promise with observable

Here is extract of my service, I would like getIssues metod to return observable, rather than promise resolving into observable as it would seem so much more clean. I am confident there is a way, I am just a bit too new to this.

import { Injectable } from '@angular/core'; (...)

@Injectable({ providedIn: 'root', })
export class IssueService {
    private users!: Promise<Map<number, Users>;
    constructor(private http: HttpClient, private userService: UserService) {
        this.users = this.userService.getUsers()
    }

    getIssues() {
        return this.users.then(users => {
            return this.http.get<Iissue[]>(URL, OPTIONS).pipe(
                map(issues => new Issue(issue, users)),
            );
        });
    }
}

Upvotes: 1

Views: 4397

Answers (3)

Mark van Straten
Mark van Straten

Reputation: 9425

The easiest approach is to wrap a promise with Observable.from() to have it adhere to the Observable interface. But this does not change its hot/coldness and can lead to unexpected behaviour.

Observables are (by default) lazy and will only start running once you subscribe to them. Promises are eager and will start running immediately. This can result in hard to debug conditions because your observalified-promise might run & complete out-of-scope of your observable.

To resolve this you can use Observable.defer(() => myPromise()) so your promise will only be invoked (& start running) once the Observable.defer is subscribed to.

Upvotes: 4

JanRecker
JanRecker

Reputation: 1847

@Wandrille showed how to get an observable from a promise.

You could also use "from()", that should also work with Promises. Now you can use all the rxjs magic on it.

In your case, you want to switch from one stream (the promise) to another stream (the htt.get). Therefor i would use "switchMap" and after that "map" to get the date in the format you wish.

getIssues():Observable<Issue>{
    return from(this.users).pipe(
        switchMap((users:Map<number, Users>) => this.http.get(URL,OPTIONS) ),
        map( (issues: IIssue[]): Issue => new Issue(issue,users) )
    )
}

warm regards

Upvotes: 0

Wandrille
Wandrille

Reputation: 6811

function like this would work:

getIssues() {
  return mergeMap(val =>
    fromPromise(myPromise(val))
  )
}

Upvotes: 0

Related Questions