Pytanie Angular2 HTTP GET - Przesyła odpowiedź do pełnego obiektu


Mam ten prosty komponent

import {Component} from 'angular2/core';
import {RouterLink, RouteParams} from 'angular2/router';
import {Http, Response, Headers} from 'angular2/http';
import {User} from '../../models/user';
import 'rxjs/add/operator/map';


@Component({
    template: `
        <h1>{{user.name}} {{user.surname}}</h1>
    `,
    directives: [RouterLink],
})
export class UserComponent {

    user: User;

    constructor(private routeParams: RouteParams,
        public http: Http) {
            this.user = new User();
            this.http.get('http://localhost:3000/user/' + this.routeParams.get('id'))
                .map((res: Response) => res.json())
                .subscribe((user: User) => this.user = user);
        console.log(this.user);
    }
}

Dlaczego subscribe nie rzucają odpowiedzi w całości User obiekt. Kiedy loguję się user zmienna, którą mówi moja konsola User {_id: undefined, name: undefined, surname: undefined, email: undefined}. Ale mimo to wiążące dla .name i .surname w widoku działa ...

co się tutaj stało? Gdzie faktycznie jest przechowywany użytkownik?


14
2018-03-15 14:30


pochodzenie


Możliwy duplikat Jak rzutować obiekt JSON na klasę maszynopisów - Günter Zöchbauer


Odpowiedzi:


Znaleziono rozwiązanie tutaj: https://stackoverflow.com/a/29759472/2854890

Moja metoda wygląda teraz tak:

constructor(private routeParams: RouteParams,
    public http: Http) {
    this.user = new User();
    this.http.get('http://localhost:3000/user/' + this.routeParams.get('id'))
        .map((res: Response) => res.json())
        .subscribe((json: Object) => {
            this.user = new User().fromJSON(json);
        });
}

Poprawiłem Serializable przez zwrócenie obiektu na końcu, więc mogę pominąć coś takiego

var u = new User();
u.fromJSON(...);

i po prostu napisz

new User().fromJSON(json);

Serializable klasa

export class Serializable {

    fromJSON(json) {
        for (var propName in json)
            this[propName] = json[propName];
        return this;
    }

}

13
2018-03-15 21:23



W Angular 6 ta linia map () daje błąd: Argument of type '(res: Response) => Promise<any>' is not assignable to parameter of type '(value: Response, index: number) => Promise<any>'. - Kristopher Windsor
mapa zmieniła się w Angular 6. Sprawdź to: academind.com/learn/angular/snippets/... - Daniel Hitzel
@DanielHitzel Twoim pierwotnym problemem był twój console.log jest wykonywane przed otrzymaniem odpowiedzi. Nawet jeśli była na właściwej pozycji, nadpisałbyś wartość w swoim subscribe obsługi przez zwykły obiekt (this.user = user), który nie jest instancją User już (mimo to a Userkompatybilny obiekt o tych samych właściwościach). Oba problemy rozwiązuje ta odpowiedź. Jednak chciałem zwrócić uwagę, że twój rzeczywisty problem - wartości właściwości są undefined - pochodzi z innego błędu. - fishbone


Dobrą praktyką jest wykorzystywanie danych z odpowiedzi GET przy użyciu

Observable<Model>

(w odniesieniu do dokumentacji kątowej https://angular.io/guide/http) więc...

// import

import {HttpClient} from "@angular/common/http";

// na liście parametrów konstruktora

private http: HttpClient

// metoda serwisowa

getUser(): Observable<User> {return this.http.get<User>({url}, {options});}

Nie musisz robić nic więcej. Uważam to podejście za najbardziej przyjazne.


13
2017-10-11 09:17



To zadziała w przypadku większości podejść, ale nie jest rzutowane, bardziej jak asercja typu. Jeśli masz funkcję w swojej klasie export class User { test() { console.log("works"); } } Nie można uruchomić user.test (). - ovmcit5eoivc4
Aby uniknąć zamieszania dla kogokolwiek, takie podejście jest dostępne tylko w wersji Angular 4.3+, w której wprowadzono nowy HttpClient. - Darren Lewis
jest to super eleganckie rozwiązanie i bardzo czytelne. - Kerby82
@DarrenLewis, jakie podejście musimy zastosować, jeśli metoda get chce zwrócić tablicę modelu? - Anil
@Ailil Ta metoda działa dobrze również dla tablicy modelu. Tylko zamiast użytkownika umieszczasz User [] - Przemek Struciński


To nie jest obsługiwane przez TypeScript.

Widzieć Jak rzutować obiekt JSON na klasę maszynopisów po więcej szczegółów.


0
2018-03-15 14:34



Ale dlaczego i tak jesteśmy w stanie powiązać dane. Zostaje wyświetlony, a zmienna, do której się przypisuję, jest rejestrowana jako niezdefiniowana. Jak działa wtedy powiązanie - Daniel Hitzel
JSON i obiekt są wymienne w TypeScript / JS, ale utworzony obiekt będzie zawierał tylko to, co zawiera JSON, ale nie ma metod ani innych pól, które są zdefiniowane tylko w prototypie prawdziwej klasy. - Günter Zöchbauer
jeśli zmienię to na .subscribe(data => this.user = new User(data._id, data.name, data.surname, data.email)); dziennik jest wciąż taki sam. Czego potrzebuję do zalogowania się, aby uzyskać widok, do którego widok jest powiązany? - Daniel Hitzel
Jest jeszcze jeden błąd, który przeoczyłem. `console.log (this.user);` jest wykonywane przed wywołaniem żądania HTTP. this.http.get()jest asynchroniczne, co oznacza, że ​​zadanie jest zapisywane w kolejce zdarzeń przeglądarki do późniejszego wykonania, a następnie wykonywanie JS jest kontynuowane (za pomocą komendy log). Po zakończeniu wywołania HTTP wywołanie zwrotne przekazane do .subscribe(...) jest wykonywane, ale to dużo później. Przenieś wywołanie dziennika do subscribe((user: User) => { ... }); - Günter Zöchbauer