Angular2 HTTP GET - 将响应转换为完整对象

Posted

技术标签:

【中文标题】Angular2 HTTP GET - 将响应转换为完整对象【英文标题】:Angular2 HTTP GET - Cast response into full object 【发布时间】: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 是有效的..

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

【问题讨论】:

How do I cast a JSON object to a typescript class的可能重复 我看了这篇文章也不错***.com/questions/63964124/… 【参考方案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://***.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 上面指出的那样)

以上是关于Angular2 HTTP GET - 将响应转换为完整对象的主要内容,如果未能解决你的问题,请参考以下文章

某些 GET 请求对预检的 Angular2 响应无效(重定向)

Angular 2:如何访问 HTTP 响应正文?

Angular2 - HTTP 200 被视为错误

Angular 2 Http 获取响应示例

Angular2:http.get 返回“请求的资源上不存在‘Access-Control-Allow-Origin’标头。”

Angular2:将 XML 转换为 JSON