makkasi
makkasi

Reputation: 7328

How to correctly use Observable data, to modify this data with other Observable and to return it as Observable

I have angular2 project and in it I have this class:

class Application {
    id: number;
    last_android_releasse_url: string;
    last_android_releasse: Release;
    last_ios_releasse_url: string;
    last_ios_releasse: Release;
}

I fetch all applications and load them with the | async pipe this way:

this.asyncApps = this.appService.getAll(this.params)
      .do((data: any) => {
        this.count = data.count;
      }).map(data => {
        return data.apps;
      });

What I need is to load every release object for every app inside the data.apps and to return observable for the asyncApps to work with the async pipe. I wasn't sure how to ask my question so I accept proposals for title change. So the final code should do something like this:

this.asyncApps = this.appService.getAll(this.params)
      .do((data: any) => {
        this.count = data.count;
      }).map(data => {
        for (let app of data.apps) {
          this.http.get(app.last_android_releasse_url).subscribe(
            release_data => {
              app.last_android_releasse = release_data.json().last_android_releasse;
            },
            error => this.alertService.showError(error.etext)
          );
          this.http.get(app.last_ios_releasse_url).subscribe(
            release_data => {
              app.last_ios_releasse = release_data.json().last_ios_releasse;
            },
            error => this.alertService.showError(error.etext)
          );
        }
        return data.apps;
      });

And this one works, but I was thinking about something with flatMap or forkJoin. Just doesn't seem like the right solution to me. Could you help me clear that please.

Upvotes: 0

Views: 258

Answers (1)

Vamshi
Vamshi

Reputation: 9341

You are right, you can use flatMap . Thanks for asking , here is what I attempted.

this.asyncApps = this.appService.getAll(this.params)
      .do((data: any) => {
        this.count = data.count;
      })
      .flatMap(data => Observable.from(data.apps))
      .flatMap(app => Observable.forkJoin(
            this.http.get(app.last_android_releasse_url).map(d => d.json().last_android_releasse),
            this.http.get(app.last_ios_releasse_url).map(d=>d.json().last_ios_releasse))
          .first()
          .map(res => Object.assign(app, {
                  last_android_releasse : res[0],
                  last_ios_releasse : res[1]})
           )
      );

Let me know if its working.


Here is what I did

this.asyncApps = this.appService.getAll(this.params)

Perform network call

          .do((data: any) => {
            this.count = data.count;
          })

Update count to number of result

          .flatMap(data => Observable.from(data.apps))

Convert stream of list to stream of individual items

          .flatMap(app => Observable.forkJoin(

For each app , am converting app without response to app with response data. As its asynchronous and needs Observable, used flatMap.

                this.http.get(app.last_android_releasse_url).map(d => d.json().last_android_releasse),
                this.http.get(app.last_ios_releasse_url).map(d=>d.json().last_ios_releasse))

Do separate calls in parallel and combine the result in stream of array

              .first()

Get the first result

              .map(res => Object.assign(app, {
                      last_android_releasse : res[0],
                      last_ios_releasse : res[1]})
               )

convert the result to app with result

          );

Finally we should have a stream of apps with response in each of them.

Upvotes: 1

Related Questions