Skip to content
Advertisement

RXJS – return observable value when doing a map

I have an array of inputIds where I am doing a map that returns a name and value object. Inside the map, I am calling this.inputService.getInputFieldObject which returns an Observable<InputValue>. How do I return the value of the subscription instead of returning an array of subscription values? So I could have attributes returned as an array with only name and value.

const attributes = inputIds.map((attributeName: string) => {
  // this.inputService.getInputFieldObject returns Observable<InputValue>

  const inputSubscription = this.inputService.getInputFieldObject(attributeName).subscribe((val) => val.value)

  return {
    name: attributeName,
    value: inputSubscription, // is there a getValue method to get value of subscription?
  };
});

Advertisement

Answer

You can wrap it in a forkJoin and subscribe to that, like this:

forkJoin(
   inputIds.map((attributeName: string) => 
       this.inputService.getInputFieldObject(attributeName).pipe(
           map((inputValue: InputValue) => { 
               return { 
                   name: attributeName,
                   value: inputValue
               };
           })
       )
).subscribe(
    (result: { name: string, value: InputValue }[]) => {
        // do what you need to do with the result
    },
    (error) => {
        // add code here if you need to handle failure on any of the calls 
        // to this.inputService.getInputFieldObject(), or any processing thereafter.
    }
);

To explain what the code is doing:

1. This calls inputService.getInputFieldObject() for each attributeName in inputIds. This returns an array of Observables<InputValue>

inputIds.map((attributeName: string) => this.inputService.getInputFieldObject(attributeName))

2. We pipe each call to this.inputService.getInputFieldObject() to a map to return both the attributeName and inputValue. So, instead, we are now returning an array of Observables<{ name: attributeName, value: inputValue }>

this.inputService.getInputFieldObject(attributeName).pipe(
    map((inputValue: InputValue) => { 
        return { 
            name: attributeName,
            value: inputValue
        };
    })
)

3. Then we wrap ALL of these with a forkJoin and then subscribing to that. forkJoin can receive an array of Observables and waits for all of them to complete. By doing so, we are waiting for all the observables to return their (final) emitted values before we process the result. So the value you receive in the subscribe() would be an array of { name: string, value: InputValue }:

forkJoin(
    ....
).subscribe((result: { name: string, value: InputValue }[]) => {
  // do what you need to do with the result
})

Important Note:

If any of the calls to inputService.getInputFieldObject() fails, the error callback on your subcribe() will be triggered, instead of the success callback.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement