【问题标题】:Angular2 HTTP GET - Cast response into full objectAngular2 HTTP GET - 将响应转换为完整对象
【发布时间】:2016-07-01 01:30:29
【问题描述】:

我有这个简单的组件

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);
    }
}

为什么subscribe 不将响应转换为完整的User 对象。当我记录user 变量时,我的控制台说User {_id: undefined, name: undefined, surname: undefined, email: undefined}。但尽管如此,绑定到视图中的.name.surname 是有效的..

这里发生了什么?用户实际存储在哪里?

【问题讨论】:

标签: typescript angular


【解决方案1】:

TypeScript 不支持。

请参阅How do I cast a JSON object to a typescript class 了解更多详情。

【讨论】:

  • 但是为什么我仍然能够绑定到数据。它被显示,而我绑定的变量被记录为未定义.. 那么绑定如何工作
  • JSON 和对象在 TypeScript/JS 中是可以互换的,但是创建的对象只会包含 JSON 所包含的内容,而不会包含仅在真实类的原型中定义的方法或其他字段。跨度>
  • 如果我把它改成.subscribe(data =&gt; this.user = new User(data._id, data.name, data.surname, data.email));,日志还是一样的。我需要登录什么才能获取视图绑定的对象?
  • 我还漏掉了另一个错误。 `console.log(this.user);` 在发出 HTTP 请求之前执行。 this.http.get() 是异步的,这意味着任务在浏览器事件队列中排队等待稍后执行,然后继续执行 JS(使用您的 log 命令)。当 HTTP 调用完成后,将执行传递给 .subscribe(...) 的回调,但这要晚得多。将日志调用移至subscribe((user: User) =&gt; { ... });
【解决方案2】:

在这里找到解决方案:https://stackoverflow.com/a/29759472/2854890

我的方法现在看起来像这样:

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);
        });
}

我通过最后返回对象来增强Serializable,所以我可以省略类似

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

然后写

new User().fromJSON(json);

Serializable

export class Serializable {

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

}

【讨论】:

  • 在 Angular 6 中 map() 行给出错误:Argument of type '(res: Response) =&gt; Promise&lt;any&gt;' is not assignable to parameter of type '(value: Response, index: number) =&gt; Promise&lt;any&gt;'.
  • 地图在 Angular 6 中发生了变化。检查一下:academind.com/learn/angular/snippets/…
  • @DanielHitzel 您最初的问题是您的console.log 在响应到达之前执行。即使它位于正确的位置,您也会用一个普通对象 (this.user = user) 覆盖您的 subscribe 处理程序中的值,该对象不再是 User 的实例(尽管如此,User 兼容对象具有相同的特性)。这个答案解决了这两个问题。但是,我想指出您的实际问题 - 属性值为 undefined - 源于另一个错误。
  • 以更多经验查看代码,是的,这似乎是真的:D
【解决方案3】:

良好的做法是使用来自 GET 响应的数据

Observable<Model>

(关于 Angular 文档https://angular.io/guide/http) 所以……

// 进口

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

//在构造函数参数列表中

private http: HttpClient

//服务方法

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

您无需再做任何事情。我认为这种方法最友好。

【讨论】:

  • 这适用于大多数方法,但它不会强制转换,更像是类型断言。如果你的类中有函数export class User { test() { console.log("works"); } } 你不能运行 user.test()。
  • 为了避免让任何人感到困惑,这种方法仅在引入新 HttpClient 的 Angular 4.3+ 中可用。
  • @DarrenLewis,如果 get 方法想要返回 Model 数组,我们必须使用什么方法?
  • @Anil 此方法也适用于模型数组。只是代替 User 你把 User[]
  • 作者的问题是他的log命令在响应到达之前就执行了。在我看来,您的回答与作者的问题完全无关。此外,他要求一个“完整的User 对象”,我将其解释为User 类实例。因此,即使他的日志位于正确的位置,您的答案也将是错误的,因为它将返回一个普通对象(如 ovmcit5eoivc4 上面指出的那样)
猜你喜欢
  • 2016-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
  • 2019-11-21
  • 2017-10-17
相关资源
最近更新 更多