astrodedl
astrodedl

Reputation: 210

RxJS / Angular 7 : forkjoin with different callbacks

I'm kinda new to rxjs (we've been stuck with angularJS for a long time and finally getting out of our technical debt).

Using angular7, I have a list of requests like this. Using forkJoin, I manage it like this :

let requests = []
for (let asset in this.assets)
{
    if(asset.enabled)
        requests.push(this.apiService.postAsset(oAsset))
}
return forkJoin(requests)

And it works fine, I get my array of responses. however I'm a bit stuck trying to figure out how to get different callbacks depending on asset type. I'd like something like

private saveAssets(): Observable<any>{
    let requests = []
    for (let asset in this.assets)
    {
      //asset exists already
      if(asset.id)
      {
        requests.push(this.apiService.putAsset(asset)
          .subscribe(response => {
           // do something with asset
          }))
      }
      else
      {
        requests.push(this.apiService.postAsset(asset)
          .subscribe(response => {  
            asset.id = response.id
            // do some more thing with asset
          }))
      }
    }
    return forkJoin(requests)
    //keep the forkjoin because I want to do something when everything is done
}

But it won't work. Error given ERROR TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. is related to function calling the one doing the request which looks like this (it worked fine without the single 'subscribes') :

this.saveAssets()
    .subscribe(responses => {
        console.log(responses)
    })

Any help, or hint about thing to look for, would be much appreciated... I'll allocate more time learning RxJS but for now I'm just trying to get this small thing to work in a not-too-dirty way.

Thank you so much !

Upvotes: 0

Views: 1854

Answers (1)

Anto Antony
Anto Antony

Reputation: 872

Subscribing to an observable will return Subscription. But the forkjoin will expect the array of observable. In your case this will be an array of Subscriptions. Use map operator for each request as follows to solve your issue.

let requests = []
for (let asset in this.assets)
{
  //asset exists already
  if(asset.id)
  {
    requests.push(this.apiService.putAsset(asset)
      .pipe(map(response => {
           // do something with asset or alter the response from here
          return response; 
         })
        ));
  }
  else
  {
    requests.push(this.apiService.postAsset(asset)
       .pipe(map(response => {
         // do something with asset or alter the response from here
         return response; 
      })));
  }
}
return forkJoin(requests).

The Map operator applies a function of your choosing to each item emitted by the source Observable, and returns an Observable that emits the results of these function applications.

If you don't want to alter the final result, Use tap operator.

Upvotes: 4

Related Questions