1

I'm totally stuck with this. I have searched the internet up and down and spent at least two hours looking at SO answers on the HttpClient, without getting anywhere.

I have this basic service that should retrieve some data from a REST endpoint

import { Injectable, Inject } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class UtilityService {
  public getSavedProject() {
    return this.http.get(this.baseUrl + 'api/ProjectAction/RetrieveActions');
  }
}

This code is then to be used in a second service where I added the following code

@Injectable({
  providedIn: 'root'
})
export class ProjectTreeActionService {
  //...
  private data;

  constructor(private utilityService: UtilityService) {}

  getSavedProject() {

    this.utilityService
      .getSavedProject()
      .subscribe((result) => this.data = result[0].toString() );

    return this.data;
  }

This is the most basic behaviour described in more or less every tutorial and example. However in my case the last line return this.data always gives me an undefined.

I already checked that the expected result is correctly retrieved by logging it to the console in the subscribe callback, but I can't get the value written to the class property where I need it to continue working with it.

What part am I missing?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Markus Deibel
  • 1,261
  • 20
  • 26
  • You are making an asynchronous call to the getSavedProject() function of ProjectTreeActionService. Try placing 'return this.data' after this.data = result[0].toString() – Abhishek Sharma Jul 15 '19 at 13:24
  • Basically the same issue was just asked here https://stackoverflow.com/questions/57040160/parsing-json-file-working-only-for-html-and-not-for-typescript-code – MoxxiManagarm Jul 15 '19 at 13:27
  • The part you're missing is __asynchronous__. When you execute `utiliService.getSavedProject().subscribe(...)`, you basically tell your program : "get the result of the observable returned by utiliService.getSavedProject" and assign its value to the class property `data`". then you return the class property `data` which is `undefined` because you don't have the result yet. Then you have the result and assign its value to data, but that's too late. – Florian Jul 15 '19 at 13:56
  • 1
    [This could help you to get a better understanding](https://medium.com/@luukgruijs/understanding-creating-and-subscribing-to-observables-in-angular-426dbf0b04a3/) – Florian Jul 15 '19 at 14:01
  • Thanks for the hints, I finally got this solved. – Markus Deibel Jul 16 '19 at 08:31

2 Answers2

4

Ideally, the getSavedProject() should return an Observable wrapping the value that you should be mapping inside the getSavedProject() method.

Here, give this a try:

@Injectable({
  providedIn: 'root'
})
export class ProjectTreeActionService {

  private data;

  constructor(private utilityService: UtilityService) {}

  getSavedProject() {
    return this.utilityService
      .getSavedProject()
      .pipe(
        map(result => result[0].toString())
      );
  }
}

Assuming that this method would be used in a Component, to extract the data that is returned by the getSavedProject() method you will have to either subscribe to getSavedProject(). Or you will have to assign getSavedProject() to a class property and then unwrap it in the Component Template using the async pipe.

SiddAjmera
  • 38,129
  • 5
  • 72
  • 110
1

You can just subscribe to your service method in the caller.

For example -

@Injectable({
  providedIn: 'root'
})
export class ProjectTreeActionService {

  private data;

  constructor(private utilityService: UtilityService) {}

  getSavedProject(): Observable<any> {
    return this.utilityService
      .getSavedProject();
  }
}

and when you have an instance of your ProjectTreeActionService you can subscribe it there.

this.projectTreeActionServiceInstance.getSavedProject().subscribe(result => {
    //manipulate the result[0].toString() here;
});
Guruprasad J Rao
  • 29,410
  • 14
  • 101
  • 200