Home > Net >  How to return data from function implementing observable
How to return data from function implementing observable

Time:10-16

I have a requirement like below

I have a function (in let say file2.ts) which makes observable GET HTTP requests and the returns AppResponse object filled with the HTTP response. here is the code. i want appResponse object in file1.ts to be populated with file2.ts get1 call. How to achieve this?

**file1.ts**

  getProfile() {
    this.appResonse = this.file1.get1(endPoint);
  }

**file2.ts**
  get1(endPoint: string): AppResponse {
    let appResponse = new AppResponse();

    this.httpClient.get<IHttpResponse>(url).subscribe((httpResponse: IHttpResponse) => {
        appResponse.data = httpResponse.data;
    });

    return appResponse;
  }

CodePudding user response:

Although the answer by akirus answers your question, i want to add some points, as it seems that you are not familiar with async and observable concepts...

  1. A http request is an async call. That means when you make a http request, the browser will not wait for the response, but will continue to execute code after this call. And when the response is available, the the call back or subscribe method is invoked.

  2. So in the above code snippet of yours, first this line is executed in the method:

let appResponse = new AppResponse();

Then a request is sent to the server. Which is essentially this code

this.httpClient.get(url)

Then as mentioned in point 1, the next instruction is executed which is

return appResponse;

Then some point of time, the request would complete and the subscribe method is called. Executing the following code

appResponse.data = httpResponse.data;

But since you are not waiting till this point to return data to caller from file1.ts. The data would be undefined in the AppResponse

this.appResonse = this.file1.get1(endPoint);

  1. So When you want to get data from such async calls, you will have to return Promise or Observable which means, the data will be available at some point in future and the calling method will be notified when data is available. So in your case You will have to return a observable from file2.ts and subscribe in file1.ts

  2. So you code could be

**file1.ts**

  getProfile(): void {
    this.file1.get1(endPoint).subscribe(appResponse => this.appResponse = appResponse);
  }

**file2.ts**
  get1(endPoint: string): Observable<AppResponse> {
    return this.httpClient.get<IHttpResponse>(url)
                   .pipe(
                      map((httpResponse: IHttpResponse) => {
                             let appResponse = new AppResponse();
                             appResponse.data = httpResponse.data;
                             return appResponse;
                      });
                    );
  }

CodePudding user response:

file1.ts

export class ComponentOne{

    appResponse$: Observable<AppResponse>;
    
    constructor(private serviceOne: ServiceOne){
        this.appResponse$ = this.serviceOne.get1();
        
        this.appResponse$.pipe(
            map(httpResponse => httpResponse.data)
        ).subscribe(data =>{
            console.log(data);
        });
    }
    
}

file2.ts

@Injectable({
    providedIn: 'root'
})
export class ServiceOne{
    get1(endPoint: string): Observable<AppResponse> {
        return this.httpClient.get<IHttpResponse>(url);
    }
}

CodePudding user response:

The normal approach is to have:

return this.httpClient.get(url);

in file2 and then subscribe to that response in file1, setting the appResponse to the response data.

If for some reason you really need to subscribe in file2 then you can either return a promise that resolves when the data is retrieved or have some sort of observer/subscriber pair that you subscribe to in file1 when the data is received.

All of these are just extra steps that can help you save that data in file2 while also sending it to file1 but if that is not the case then simply subscribing in file1 should be the go to approach.

Edit: Example of the alternative options

  • Related