0

I have a service to get a list of properties, inside that service I am modifying the response using map and returning final array as Observable.

But How I can get that final array as simple JSON from service to my component. This what I have done so far.

SERVICE

getPropertyList(){
    let propertyList$ : Observable<any> = this._http.get('http://localhost:3000/...');

    return propertyList$.pipe(
      map(data => {
        // do your transformations
        let listArray: Array<any> = data.response.dataset;
        listArray.forEach(list => {
          list.name = 'jhon deo';
        })
        return listArray;
      })
    )
}

Component

this._service.getPropertyList()
 .subscribe({
   next: (result) => {
     console.log(result);
   },
   error: (err) => {
     console.log(err);
   }
})

I am trying to achieve it like this from Component -

getData(){
   const listData: Array<any> = this._service.getPropertyList();
}
RAHUL KUNDU
  • 745
  • 2
  • 12
  • 33
  • `getPropertyList` doesn't return an array, it returns an *observable* of an array. You need to subscribe, or use `| async` in the template, to resolve the array value. See e.g. https://angular.io/guide/observables. – jonrsharpe Mar 18 '21 at 13:51
  • I am trying to return it not an observable. I am trying to get it as json. – RAHUL KUNDU Mar 18 '21 at 13:54
  • You can't, because you're getting that data from a network call, which is asynchronous. – jonrsharpe Mar 18 '21 at 13:54
  • Does this answer your question? [Angular 2 - Return data directly from an Observable](https://stackoverflow.com/questions/37867020/angular-2-return-data-directly-from-an-observable) – jonrsharpe Mar 18 '21 at 14:03

1 Answers1

2

Initially, when working with observables, it can feel like you want to get the data out of the observable and store it someplace else. But, usually this isn't necessary. Most of the time, you can simply use various pipeable operators to design the behavior and data transformation of your emitted values.

You say you want this in your component:

getData() {
   const listData: Array<any> = this._service.getPropertyList();
}

But, you could just define the data as an observable that delivers the data whenever it is available instead of defining it as a method:

data$: Observable<Array<any>> = this._service.getPropertyList();

Doing it this way makes your component simpler, because the component does not need to be concerned with fetching the data, it simply references the observable, which will deliver the data any time it changes.

I like to think of the $ as a little indicator that this thing is a "value that is automatically updated" (observable).

Now, instead of subscribing in your component (previously):

this._service.getPropertyList()
 .subscribe({
   next: (result) => {
     console.log(result);
   },
   error: (err) => {
     console.log(err);
   }
})

You can simplify by defining your data$ as an observable and leveraging Angular's async pipe to handle the subscription for you, from the template:

data$ = this._service.getPropertyList().pipe(
   tap(result => console.log(result)),
   catchError(err => console.log(err))
});
<ul>
  <li *ngFor="let item of data$ | async">{{ item.name }}</li>
</ul>

Operators Used:

  • tap - Perform any side effect logic without altering the emitted values
  • catchError - catch errors that occur in observable stream
BizzyBob
  • 12,309
  • 4
  • 27
  • 51