Angular map HttpClient.Post
Asked Answered
C

2

6

So I finally decided to catch up with the times and migrate some old angular Http stuff to HttpClient.

The app used to run on a bunch of Promise based code, which has since been removed (mostly).
My old Promise function looked something like this:

public getUser(profileId: number): Promise<User> {
    return this.http.post("/api/url", postObject, HttpSettings.GetDefaultHttpRequestOptions());
    .map(u => new User(u))
    .catch(this.handleError)
    .toPromise();
}

My new HttpClient function is much nicer:

public getUser(profileId: number): Observable<any> {
    return this.http.post("/api/url", postObject, HttpSettings.GetDefaultHttpRequestOptions());
}

But what I don't like currently is that in each subscription to this, I now have to map the data to an instance of User...

service.getUser(1).subscribe(data => {
    data = new User(data);
});

This is the simplest .map which I have, some post methods actually return a rather complex object which map to many new object instances.

I see with HttpClient.get you can Type assert the response, can I do something like this with .post so that I don't have to map the data to a new User in each of the subscriptions?

Note: Eventually I will migrate this again to a better architecture where you actually subscribe to a User variable, but for now I just want to implement HttpClient.

Corporative answered 1/2, 2018 at 11:5 Comment(1)
can I do something like this with .post so that I don't have to map the data to a new User in each of the subscriptions <= Yes, the exact same generic to specify the return type is available for post and also put. It will not convert automatically to an object but you can specify an interface for the returned data. Alternatively you can chain map in the service like you did previously.Sensory
S
7

can I do something like this with .post so that I don't have to map the data to a new User in each of the subscriptions <= Yes, the exact same generic to specify the return type is available for post and also put. It will not convert automatically to an object but you can specify an interface for the returned data. Alternatively you can chain map in the service like you did previously but I recommend you use the pipeable operators.


Example using pipeable operators to mimic what you had in your previous code.

import { map } from 'rxjs/operators/map';

public getUser(profileId: number): Observable<User> {
    return this.http.post("/api/url", postObject, HttpSettings.GetDefaultHttpRequestOptions())
        .pipe(map(data => new User(data)));
}

Example where User is nothing more than an interface with properties.

If the data itself is json representative of an interface that has properties you can convert it directly.

export interface User {
  userId: number;
  name: string;
}


public getUser(profileId: number): Observable<User> {
    return this.http.post<User>("/api/url", postObject, HttpSettings.GetDefaultHttpRequestOptions());
}
Sensory answered 1/2, 2018 at 11:11 Comment(7)
I'm conflicted on whether this answer makes me happy, or infuriated because I swear that I tried .post<User> and it wasn't working.... Can confirm that it works..... :( - thankyou.Corporative
The .pipe method on the other hand is excellent to know about and I will certainly need to implement that later on.Corporative
@Corporative - I added a link to the rxjs page about pipeable operators, these provide more insight as to how to use them.Sensory
@Corporative - I added the import statement. The only requirement is that you are using RxJs version 5.5 or later.Sensory
How does map(data) handle this process if data is an array and not an object? - How do I ... map(data => { return data.map( ele => new Thing(ele)); } to return an Array<Thing>.Corporative
@Corporative - Your code sample looks fine, what is wrong with it? Did you change the signature on the method to return an observable of Thing[] instead of just Thing maybe?Sensory
I made a second question: #48562660 - I would appreciate it if you could please have a glance at it.Corporative
A
2

If you import your User class in the service, you can map it back to a User object by add <User> after the post and before the ()

public getUser(profileId: number): Observable<any> {
    return this.http.post<User>("/api/url", postObject, HttpSettings.GetDefaultHttpRequestOptions());
}
Ambler answered 1/2, 2018 at 11:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.