Etchelon
Etchelon

Reputation: 882

Rxjs: add data to elements of array returned from http response

Following this question: Add data to http response using rxjs

I've tried to adapt this code to my use case where the result of the first http call yields an array instead of a value... but I can't get my head around it. How do I write in rxjs (Typescript) the following pseudo code?

call my server

obtain an array of objects with the following properties: (external id, name)

for each object, call another server passing the external id

for each response from the external server, obtain another object and merge some of its properties into the object from my server with the same id

finally, subscribe and obtain an array of augmented objects with the following structure: (external id, name, augmented prop1, augmented prop2, ...)

So far the only thing I was able to do is:

    this._appService
        .getUserGames()
        .subscribe(games => {
            this._userGames = _.map(games, game => ({ id: game.id, externalGameId: game.externalGameId, name: game.name }));
            _.forEach(this._userGames, game => {
                this._externalService
                    .getExternalGameById(game.externalGameId)
                    .subscribe(externalThing => {
                        (<any>game).thumbnail = externalThing.thumbnail;
                        (<any>game).name = externalThing.name;
                    });
            });
        });

Thanks in advance

Upvotes: 0

Views: 1651

Answers (2)

Etchelon
Etchelon

Reputation: 882

I found a way to make it work. I'll comment the code to better explain what it does, especially to myself :D

this._appService
        .getUserGames() // Here we have an observable that emits only 1 value: an any[]
        .mergeMap(games => _.map(games, game => this._externalService.augmentGame(game))) // Here we map the any[] to an Observable<any>[]. The external service takes the object and enriches it with more properties
        .concatAll() // This will take n observables (the Observable<any>[]) and return an Observable<any> that emits n values
        .toArray() // But I want a single emission of an any[], so I turn that n emissions to a single emission of an array
        .subscribe(games => { ... }); // TA-DAAAAA!

Upvotes: 1

slaesh
slaesh

Reputation: 16917

Don't use subscribe. Use map instead. Can't test it, but should look more like this:

this._appService
    .getUserGames()
    .map(games => {
        this._userGames = _.map(games, game => ({ id: game.id, externalGameId: game.externalGameId, name: game.name }));
        return this._userGames.map(game => { /* this should return an array of observables.. */
            return this._externalService
                .getExternalGameById(game.externalGameId)
                .map(externalThing => {
                    (<any>game).thumbnail = externalThing.thumbnail;
                    (<any>game).name = externalThing.name;
                    return game;
                });
        });
    })
    .mergeAll()
    .subscribe(xx => ...); // here you can subscribe..

Upvotes: 0

Related Questions