アンギュラー2 HttpClientでREST経由でデータを取得しようとしています。私はここで角度のチュートリアルに従っています https://angular.io/tutorial/toh-pt6 とヒーローとHTTPセクションでは、httpを介してヒーローデータを取得するために使用されるこのコードスニペットが表示されます。
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 Ideaを使用していますが、response.json()呼び出しに赤い線があり、ng buildを使用してビルドしようとしてもエラー。
プロパティ 'json'はタイプ 'Object'に存在しません。
json().data
の代わりにjson().results
があります。チュートリアルによれば、サーバーはdata
フィールドを持つオブジェクトで応答しましたが、自分のサーバーはresults
フィールドを持つオブジェクトで応答するためです。チュートリアルを少し下にスクロールすると、このポイントが表示されます。
サーバーが返すデータの形状に注意してください。この特定のインメモリWeb APIの例は、データプロパティを持つオブジェクトを返します。あなたのAPIは何か他のものを返すかもしれません。 Web APIに合わせてコードを調整します。
これを修正するために、私はこのようなことを試みました
(response: Response) => response.json().results as Order[]
私がそれをしたとき、.json()メソッドは解決されましたが、別のエラーがポップアップしました
タイプPromiseにはプロパティ結果が存在しません
インターフェースを定義することでそれを修正しようとしました
interface OrderResponse {
orders: Order[];
}
そしてget呼び出しを修正しました
.get<OrderResponse>(url)...
しかし、それもうまくいきませんでした。別のエラーがポップアップしました
タイプ「OrderResponse」は、タイプ「Response」に割り当てることができません。
1つの注意点は、チュートリアルではAngular HttpModuleを使用しましたが、私のアプリケーションでは新しいAngular HttpClientModuleを使用しているため、エラーが発生する可能性があることです。
私はAngular 2が初めてであり、これを使用して作成する最初のアプリです。上記のコードが新しいHttpClientModuleで無効になった場合、新しいHttpClientModuleで同じことを達成する方法についての助けをいただければ幸いです。
私は同様の質問を見つけました プロパティ 'json'はタイプ '{}'に存在しません および プロパティはタイプ 'オブジェクト'に存在しません しかし、そこの答えは私を助けませんでした。
更新
コメントが示唆したように、新しい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;
});
私は完全に理解していますが、私の問題は、コードがコンポーネント内ではなくサービス内にあるため、subscribeを呼び出して結果をインスタンスフィールドに割り当てることはあまり意味がないことです。
PromiseにラップされたOrderの配列を返すサービスが必要です。私のコンポーネントは次のような呼び出しを行うことができます
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);
}
更新:rxjs> v5.5の場合
いくつかのコメントや他の回答で述べたように、デフォルトでは HttpClient は応答のコンテンツをオブジェクトにデシリアライズします。一部のメソッドでは、結果をダックタイプするためにジェネリック型引数を渡すことができます。これがjson()
メソッドがもうない理由です。
import {throwError} from 'rxjs';
import {catchError, map} from 'rxjs/operators';
export interface Order {
// Properties
}
interface ResponseOrders {
results: Order[];
}
@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<ResponseOrders >(this.baseUrl,{
params
}).pipe(
map(res => res.results || []),
catchError(error => _throwError(error.message || error))
);
}
toPromise()
を呼び出すだけで、返されたObservable
をPromise
に簡単に変換できることに注意してください。
元の回答:
あなたの場合、次のことができます
バックエンドが次のようなものを返すと仮定します:
{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インターセプターを介してアーカイブできるため、catchセクションを削除しました。 ドキュメント を確認してください。例として:
https://Gist.github.com/jotatoledo/765c7f6d8a755613cafca97e83313b9
消費するには、次のように呼び出すだけです。
// In some component for example
this.fooService.fetch(...).subscribe(data => ...); // data is Order[]
将来の訪問者のために:新しい HttpClient
(Angular 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のimportsの下にモジュールを含めることを忘れないでください。
...
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
BrowserModule,
// Include it under 'imports' in your application module after BrowserModule.
HttpClientModule,
...
],
...
将来の訪問者向け:新しいHttpClient(Angular 4.3以降)では、応答オブジェクトはデフォルトでJSONであるため、response.json()。dataを行う必要はありません。応答を直接使用するだけです。