1

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)),
            );
        });
    }
}
Akxe
  • 9,694
  • 3
  • 36
  • 71
  • why not convert promise to observable https://stackoverflow.com/questions/39319279/convert-promise-to-observable, then make a switchMap ? – Eliseo Jul 05 '18 at 22:26

3 Answers3

4

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.

Mark van Straten
  • 9,287
  • 3
  • 38
  • 57
  • Nice explanation, I kinda like the possibility of promise running instantly, I am even thinking to make the promise as property on service so that it is ran as soon as possible, thought I may want to switch http call with something like websocket... – Akxe Jul 06 '18 at 20:39
0

function like this would work:

getIssues() {
  return mergeMap(val =>
    fromPromise(myPromise(val))
  )
}
Wandrille
  • 6,267
  • 3
  • 20
  • 43
  • How I connect it with the observable? I need to use the value inside the map on the observable. – Akxe Jul 05 '18 at 21:18
0

@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

JanRecker
  • 1,787
  • 13
  • 17