2017-09-01 146 views
7

我想通过REST与角2 HttpClient获取数据。我正在关注角色教程https://angular.io/tutorial/toh-pt6英雄和HTTP部分,您将看到用于通过http获取英雄数据的代码片段。属性'json'不存在类型'对象'

getHeroes(): Promise<Hero[]> { 
    return this.http.get(this.heroesUrl) 
     .toPromise() 
     .then(response => response.json().data as Hero[]) 
     .catch(this.handleError); 
} 

其下方是类似的版本我在我的应用程序

fetch(startIndex: number, limit: number): Promise<Order[]> { 
    let url = this.baseUrl + "&startIndex=" + startIndex + "&limit=" + limit; 

    return this.http.get(url) 
       .toPromise() 
       .then(response => response.json().results as Order[]) 
       .catch(this.handleError); 
} 

写我使用InteliJ理念并有在电话会议上response.json(红色线),甚至当我尝试使用ng build生成错误。

属性'json'在类型'Object'上不存在。

您可能会注意到,而不是json().data我有json().results。这是因为根据教程,服务器使用具有data字段的对象进行响应,但我自己的服务器使用具有results字段的对象进行响应。如果你向下滚动教程,你会看到这一点。

请注意服务器返回的数据的形状。这个特定的 内存中的Web API示例返回一个具有data属性的对象。您的 API可能会返回其他内容。调整代码以匹配您的网络 API。

在试图解决这个问题,我想是这样的

(response: Response) => response.json().results as Order[] 

当我做的是,以.json()方法得到了解决,但另一个错误弹出该

属性结果不存在类型Promise

我试图通过定义一个接口

interface OrderResponse { 
    orders: Order[]; 
} 

并修改了get调用到

.get<OrderResponse>(url)... 

但也没有工作。弹出另一个错误

类型'OrderResponse'不可分配给'Response'类型。

有一点值得注意的是,在本教程中他们使用了角的HttpModule,但在我的应用我用新的角度HttpClientModule所以也许这就是错误的到来。

我是Angular 2的新手,这是我用它创建的第一个应用程序。如果上面的代码不再适用于新的HttpClientModule,我将不胜感激任何有关如何实现与新的HttpClientModule相同的帮助。

我发现了类似的问题Property 'json' does not exist on type '{}'Property does not exist on type 'object'但没有任何答案帮助我。

更新

正如评论认为存在一种新HttpClientModule无以.json()方法。我仍然希望能够帮助您获得与新模块相同的效果。从引导他们做了这样的事情

http.get<ItemsResponse>('/api/items').subscribe(data => { 
    // data is now an instance of type ItemsResponse, so you can do this: 
    this.results = data.results; 
}); 

这一点我完全理解,但我的问题是,该代码是不是一个组件内,但一个服务调用订阅和结果分配给一个实例字段不会太大感。

我需要我的服务返回包裹在Promise中的Orders数组。我的组件可以直接拨打电话一样

this.orderService.fetch(0, 10).then(orders => this.orders = orders) 

我还以为我的服务声明一个局部变量取方法,这样我可以做

.subscribe(data => { 
    this.orders = data.results; 
} 
// and out of the get call I return my local variable orders like 
return Promise.resolve(orders) 

但是,这没有多大意义的,我因为对.get()的调用是异步的,即使在所有数据都被提取并且orders数组可能为空之前,该方法可能会返回。

更新

如这里要求是对的HandleError

private handleError(error: any): Promise<any> { 
    console.log('An error occured ', error); 
    return Promise.reject(error.message || error); 
} 
+3

HttpClient API中没有.json()方法。您正在关注的教程使用旧的Http API。请查看https://angular.io/guide/http –

+1

就像@ Jota.Toledo说的那样,有两个http客户端--Http和HttpClient。 HttpClient是新的,不再使用.json()方法。 – matmo

+0

@matmo感谢您的输入。我更新了我的问题。请看一看。谢谢 – ivange94

回答

2

Assumming的代码,后端返回是这样的:

[{},{},{},...{}] 

更新:现在的后端返回{results: [{},{}]}

JSON格式,其中每{}是序列化对象,你将需要:

// Somewhere in your src folder 

export interface Order { 
    // Properties 
} 

import { HttpClient, HttpParams } from '@angular/common/http'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/catch'; 
import 'rxjs/add/operator/map'; 

import { Order } from 'somewhere_in_src';  

@Injectable() 
export class FooService { 
ctor(private http: HttpClient){} 

fetch(startIndex: number, limit: number): Observable<Order[]> { 
    let params = new HttpParams(); 
    params = params.set('startIndex',startIndex.toString()).set('limit',limit.toString()); 
    // base URL should not have ? in it at the en 
    return this.http.get(this.baseUrl,{ 
     params 
    }) 
    .map(res => res.results as Order[] || []); 
    // in case that the property results in the res POJO doesnt exist (res.results returns null) then return empty array ([]) 
    } 
} 

我删除闭锁段,因为这可以通过一个HTTP拦截存档。检查the docs。作为例子:

https://gist.github.com/jotatoledo/765c7f6d8a755613cafca97e83313b90

而且要消耗你只需要调用它像:

// In some component for example 
this.fooService.fetch(...).subscribe(data => ...); // data is Order[] 
+0

谢谢。似乎代码假设我的服务器将返回一个订单数组。我的服务器实际上返回一个带有.results字段的对象,这是一个订单数组。类似于{results:[]}。 – ivange94

+0

病毒更新@ ivange94,但我认为最好的办法是删除后端的封装级别 –

+0

还捕获返回类型Observable上不存在属性捕获的错误 ivange94

22

对于未来的游客:在新HttpClient(4.3+角),该response对象JSON默认情况下,所以你不需要做response.json().data了。直接使用response

(从官方文档修改):

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

@Component(...) 
export class YourComponent implements OnInit { 

    // Inject HttpClient into your component or service. 
    constructor(private http: HttpClient) {} 

    ngOnInit(): void { 
    this.http.get('https://api.github.com/users') 
     .subscribe(response => console.log(response)); 
    } 
} 

不要忘了导入和包括模块下进口在项目的app.module.ts

... 
import { HttpClientModule } from '@angular/common/http'; 

@NgModule({ 
    imports: [ 
    BrowserModule, 
    // Include it under 'imports' in your application module after BrowserModule. 
    HttpClientModule, 
    ... 
    ], 
    ... 
+1

用一个简单明了的例子真的很简单的解释!如果每个人都能给出如此有用的答案,那就太好了。 –