0

I am trying to get the data from the service in to the component below is my service

Service.ts

export class PrjService {
  tDate: Observable<filModel[]>;
  prjData:Observable<filModel[]>;
entityUrl;
constructor(){
this.entityUrl = 'PrjDetail/GetByRep';
    this.tDate = service.get<ShipDateFilterModel[]>(this.entityUrl);
}

And the component where I try to retrieve is like below

export class RFComponent implements OnInit {
  cachedResults: any[];
  shipToData: any;

constructor(private psService: PrjService)
{}
  ngOnInit() {
     this.psService.tDate.subscribe(x => this.cachedResults = x);
     this.filterData = [...new Set(this.cachedResults.map(item => item.cus_name))].filter(Boolean);
  }

Here whenever the Call to the service is made this.cachedResults is undefined and I get the error in the below like where I am trying to filter

ERROR TypeError: Cannot read property 'map' of undefined

Not sure what I am missing here

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
trx
  • 2,077
  • 9
  • 48
  • 97
  • See the aforementioned [suggested duplicate](https://stackoverflow.com/q/14220321/1260204). Asynchronous calls are a common and critical building block in writing/designing an application. It is critical that you understand how to work with asynchronous calls in javascript, and by extension typescript. Understanding these core concepts will help you become a better programmer and also ensure you do not keep "stubbing your toe" on the same problem. – Igor Sep 05 '19 at 20:16
  • @Igor the sample explains about the Ajax calls – trx Sep 05 '19 at 20:21
  • It's all the same, it's an asynchronous call where you subscribe an action to occur once the result is retrieved. It matters little if its an observable, promise, ajax call from jquery, etc. The concept is the same. That said if you want a specific example to rxjs here is another similar duplicate: [How do I return the response from an Observable/http/async call in angular?](https://stackoverflow.com/q/43055706/1260204) – Igor Sep 05 '19 at 20:28
  • 1
    The short of it is that in the body of `ngOnInit` the first LoC (line of code) subscribes to an asynchronous action and in the next line of code you are already doing something with that result but that call back has not yet executed. Either duplicate has good explanations on how to deal with asynchronous calls. Once you get the hang of it you won't make "simple" mistakes like this any more so it is worth a good look as asynchronous calls are fairly prolific in most apps. – Igor Sep 05 '19 at 20:30
  • I think what Igor is trying to say is you need to know that subsbribing is async and the last line filterdata you need to move in the subscibe function along where you are assigning cachedresults – joyBlanks Sep 05 '19 at 20:33

1 Answers1

1

Since you are making an asynchronous call, by the time control reaches filteredData statement, cachedResults value isn't fetched from the service. That is the reason for the undefined error.

To solve the problem, you have to execute the statement after the service call is completed and data is returned as response.

 ngOnInit() {
     this.psService.tDate
     .subscribe(x => {
        this.cachedResults = x;
        this.filterData = [...new Set(this.cachedResults.map(item => item.cus_name))].filter(Boolean);
     });
  }

Another approach would be to use the finally method of Observable object.

 ngOnInit() {
        this.psService.tDate
        .finally(() => {
             this.filterData = [...new Set(this.cachedResults.map(item => item.cus_name))].filter(Boolean);
         })
        .subscribe(x => {
           this.cachedResults = x;
        });
    }

Here, the finally method is called after the observable completes or when error occurs.

Nikhil
  • 6,493
  • 10
  • 31
  • 68