2017-09-01 196 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

用一個簡單明瞭的例子真的很簡單的解釋!如果每個人都能給出如此有用的答案,那就太好了。 –