Home > Software design >  How to add subscribe inside a map function in Angular
How to add subscribe inside a map function in Angular

Time:12-09

I am running into an issue where I would like to modify the objects inside an array based on data returned from a subscription.

this.options = this.options.map(data => {
      this.workflowTemplateService.getWorkflowTemplateStatistics(data.id).subscribe(res => {
        const available = (res.contactsInProgress   res.contactsInWaitingRoom   res.pausedCount).toString();
        const waitingRoomLimit = res.waitingRoomLimit;
        const quota = available.toString()   '/'   waitingRoomLimit.toString();
        console.log("Hit quota: ", quota);
        return {...data, quota};
      });
});

I wanted to do something like this where I would be able to add the quota property to each of the objects inside the array but I am getting an error related to returning void. I was wondering if there were another way where I would able to modify the options such that I can add the quota property into the options array.

CodePudding user response:

this.options$ = of(this.options)
.pipe(
  switchMap(data => this.workflowTemplateService.getWorkflowTemplateStatistics(data.id)),
  map(res => {
    const available = (res.contactsInProgress   res.contactsInWaitingRoom   res.pausedCount).toString();
        const waitingRoomLimit = res.waitingRoomLimit;
        const quota = available.toString()   '/'   waitingRoomLimit.toString();
        console.log("Hit quota: ", quota);
        return {...data, quota};
  })
)

Now you can suscribe directly to this.options$ which is now an observable or you can used directly in the template like options$ | async

this.options$.suscribe(res => console.log(res))

CodePudding user response:

First, you should convert your observable to promise to be able to take the advantage of using async/await. You can convert your observable to promise by using firstValueFrom operator in rxjs to take the first value emitted and close the subscription after that.

const promise = firstValueFrom(this.workflowTemplateService.getWorkflowTemplateStatistics(data.id));

By converting your observable to a promise, now you can mark the map callback function as async. Here is the link about async map callback function:

Best way to call an asynchronous function within map?

and your result would be something like below

async updateOptions() {
   this.options = await Promise.all(
      this.options.map(async data => {
      const result = await firstValueFrom(this.workflowTemplateService.getWorkflowTemplateStatistics(data.id));
      ...
      return {...data, quota};
      })
   )
}
  • Related