3

I implemented an method which returns an Observable. Inside this method I am using http.post to send a request to the backend. After receiving the response, which is a JSON object, I want to store this in an Observable variable and return that variable. But somehow I didn't manage to solve that problem. In .subscribe the res variable is not stored in the postResponse variable, but I can see in the "local" console.log that the res variable has the correct value. The global console.log is empty. Furthermore I get the error:

"TS2322: Type 'ArqResponse' is not assignable to type 'Observable'" error for the return.

My code looks like this:

postARQRequest(request): Observable<ArqResponse>{
    let postResponse = new ArqResponse;
    const result = this.http.post<ArqResponse>(this.arqUrl, request)
                       .subscribe((res: ArqResponse) => { postResponse = res; console.log('shadow: ' + res)});
    console.log('global: ' + JSON.stringify(postResponse));
    return postResponse;
}

My questions are:

  1. How can I store the response body in a variable, which then can be returned?
  2. How can I "cast" an ArqResponse variable to an Observable variable?
  3. .subscribe seems to be wrong since I get:

this.arqService.postARQRequest(...).subscribe is not a function error

3 Answers 3

9

I'm guessing this is what you want:

postARQRequest(request): Observable<ArqResponse>{
    return this.http.post<ArqResponse>(this.arqUrl, request);
}

There's no need to subscribe to anything here. Given that this.http.post returns the type you want, just return that.

If you really want to store the response in a local variable, there are some ways to do that:

Use a promise instead, for getting the result. Make it observable using of later on:

async postARQRequest(request): Observable<ArqResponse>{
    let postResponse = new ArqResponse;
    postResponse = await this.http.post<ArqResponse>(this.arqUrl, request).toPromise();

    return of(postResponse);
}

Use the tap operator to react to the response, but not mutate it

postARQRequest(request): Observable<ArqResponse>{
    return this.http.post<ArqResponse>(this.arqUrl, request).pipe(
        tap((res) => ...) // do stuff with res here, but it won't be mutated
    );
}

Use the map operator to map the response to something else

postARQRequest(request): Observable<ArqResponse>{
    return this.http.post<ArqResponse>(this.arqUrl, request).pipe(
        map((res) => ...) // do stuff with res here, but it *will map to whatever you return from this handler*
   );
}
Sign up to request clarification or add additional context in comments.

Comments

1

I think this may help you

postARQRequest(): Observable<ArqResponse[]> {
 return this.http.post(this.arqUrl, request)
 .map(this.extractData()) <== passing result of function
 .catch(this.handleError()); <== passing result of function
}

handle response and error here

private extractData(res: Response) {
   let body = res.json(); 
   return body.data || { }; 
}

private handleError (error: any) {
    let errMsg = error.message || 'Server error';
    console.error(errMsg); 
    return Observable.throw(errMsg);
}

Comments

0

YThe method http.post already return an Observable, so you can directly do like that:

postARQRequest(request): Observable<ArqResponse>{
    return this.http.post<ArqResponse>(this.arqUrl, request);
}

and then subscribe to it: this.arqService.postARQRequest(...).subscribe()

If you want to transform an object to an Observable, you can use of from Rxjs6:

import { of } from 'rxjs';

// ...

// create an Observable from a value:
of(someObject);

2 Comments

But I still would not be able to store the value of res in postResponse.
What do you want to store the value into and why? are you simply displaying the value in a template? or doing more?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.