简体   繁体   中英

How to make this function wait for an HTTP request

I have this function in Angular 2 which I didn't write, but which currently works properly:

myFunction(): Observable<Song> {
    return this.user.getSong$()
        .mergeMap((track: Track) => {
            if (track.isSingle()) {
                return this.getSingle(track.getId());
            } else {
                throw 'error';
            }
        });
}

But I'm having a super hard time understanding some things about it. First question: I have read an absolute ton , but I cannot fathom the difference between mergeMap and map . I don't understand what mergeMap does. Why mergeMap here?

Now on the real problem I'm trying to solve. I need to make an HTTP call and have it finish before this returns anything. I've made another function for it that returns an Observable :

populate(sourceType: string, sourceId: number): Observable<object> {
    return this.http.get(`//populate/${sourceType}/${sourceId}`)
        .map((response: Response) => {
            return <string[]> response.json();
        });
}

When I try to combine that with my other function, I get:

myFunction(): Observable<Song> {
    return this.user.getSong$()
        .mergeMap((track: Track) => {
            if (track.isSingle()) {
                this.populate('list', track.getId()).subscribe(
                    () => {},     // I don't care what the request returns,
                    () => {},     // or if it returns an error.
                    (result) => { // I only care when it's done.
                        return this.getSingle(track.getId());
                    }
                );
            } else {
                throw 'error';
            }
        });
}

This doesn't work at all, but I can't debug the error console output and have no idea how to make it work. Help?

TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Object.subscribeToResult (Rx.js?1551417548052:8237)
    at MergeMapSubscriber._innerSub (Rx.js?1551417548052:3336)
    at MergeMapSubscriber._tryNext (Rx.js?1551417548052:3333)
    at MergeMapSubscriber._next (Rx.js?1551417548052:3318)
    at MergeMapSubscriber.Subscriber.next (Rx.js?1551417548052:10743)
    at MapSubscriber._next (Rx.js?1551417548052:4975)
    at MapSubscriber.Subscriber.next (Rx.js?1551417548052:10743)
    at MapSubscriber._next (Rx.js?1551417548052:4975)
    at MapSubscriber.Subscriber.next (Rx.js?1551417548052:10743)
    at MapSubscriber._next (Rx.js?1551417548052:4975)

Just try the following. Regards what is mergeMap , I think you need to spend some time on learning Rxjs, there are plenty of resources online. In a nutshell mergeMap is kinda like promise.then but unlike promise.then where you can return value or another promise, with mergeMap you will need to return Observable in its callback.

myFunction(): Observable<Song> {
    return this.user.getSong$()
        .mergeMap((track: Track) => {
            if (track.isSingle()) {
                return this.populate('list', track.getId()).pipe(
                        mergeMap(_=>this.getSingle(track.getId())
            );

            } else {
                throw 'error';
            }
        });
      }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM