AngularのHttpClientメモ
(Angular v.4.3.6を利用)
参考
データを取得する
import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; export interface Book { id?: number; title: string; author: string; } const url = 'http://localhost:3000'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { book: Book; constructor( private http: HttpClient ) { } ngOnInit(): void { } get(id: number) { this.http.get<Book>(`${url}/posts/${id}`) .subscribe(data => { this.book = data; }, (err: HttpErrorResponse) => { // エラー処理 if (err.error instanceof Error) { // A client-side or network error occurred. Handle it accordingly. console.log('An error occurred:', err.error.message); } else { // The backend returned an unsuccessful response code. // The response body may contain clues as to what went wrong, console.log(`Backend returned code ${err.status}, body was: ${err.error}`); } }); } }
レスポンスデータの詳細を見る
this.http .get<Book>(`${url}/posts/1`, { observe: 'response' }) .subscribe(resp => { console.log(resp); });
retry
RxJSにretryというオペレータがある。
import 'rxjs/add/operator/retry';
this.http .get<Book>(`${url}/posts/${id}`) // Retry this request up to 3 times. .retry(3) // Any errors after the 3rd retry will fall through to the app. .subscribe(...);
データを送信する
const body: Book = { title: 'foo', author: 'bar' }; this.http .post<Book>(`${url}/posts`, body) .subscribe(resp => { this.book = resp; });
Headersを追加
this.http .post(`${url}/posts`, body, { headers: new HttpHeaders().set('Authorization', 'my-auth-token'), }) // ...
URL Parametersを追加
this.http .post(`${url}/posts`, body, { params: new HttpParams().set('param', 'value') }) // ...
進捗を確認
const body: Book = { title: 'foo' + new Date().valueOf(), author: 'bar' + new Date().valueOf() }; const req = new HttpRequest('POST', `${url}/posts`, body, { reportProgress: true, }); this.http.request(req).subscribe(event => { // Via this API, you get access to the raw event stream. // Look for upload progress events. if (event.type === HttpEventType.UploadProgress) { // This is an upload progress event. Compute and show the % done: const percentDone = Math.round(100 * event.loaded / event.total); console.log(`File is ${percentDone}% uploaded.`); } else if (event instanceof HttpResponse) { console.log('File is completely uploaded!'); } });
https://angular.io/guide/http#listening-to-progress-events
応用
Interceptorサービスを登録して、リクエスト・レスポンスに処理を追加できる。
import {NgModule} from '@angular/core'; import {HTTP_INTERCEPTORS} from '@angular/common/http'; @NgModule({ // Interceptorは複数登録可能 // 登録順に処理される providers: [{ provide: HTTP_INTERCEPTORS, useClass: NoopInterceptor, multi: true, }], }) export class AppModule {}
Interceptorを利用してヘッダーを追加
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { AuthService } from './auth.service'; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private auth: AuthService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const authHeader = this.auth.getAuthorizationHeader(); // HttpRequestはイミュータブル(直接、値を変更できない) const authReq = req.clone({ headers: req.headers.set('Authorization', authHeader) }); return next.handle(authReq); } }
Interceptorを利用してログを表示
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const started = Date.now(); return next .handle(req) // Rxのstreamに影響を与えずに処理を追加 .do(event => { if (event instanceof HttpResponse) { const elapsed = Date.now() - started; // 経過時間を表示 console.log(`Request for ${req.urlWithParams} took ${elapsed} ms.`); } }); }
https://angular.io/guide/http#logging
Interceptorを利用してキャッシュ機能を実装
constructor(private cache: HttpCache) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { if (req.method !== 'GET') { return next.handle(req); } const cachedResponse = this.cache.get(req); if (cachedResponse) { return Observable.of(cachedResponse); } // キャッシュがなかった場合 return next.handle(req).do(event => { // Remember, there may be other events besides just the response. if (event instanceof HttpResponse) { this.cache.put(req, event); } }); }
/** * 以前にキャッシュされていれば、2つのResponseを返す */ intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { if (req.method !== 'GET') { return next.handle(req); } // This will be an Observable of the cached value if there is one, // or an empty Observable otherwise. It starts out empty. let maybeCachedResponse: Observable<HttpEvent<any>> = Observable.empty(); const cachedResponse = this.cache.get(req); if (cachedResponse) { maybeCachedResponse = Observable.of(cachedResponse); } const networkResponse = next.handle(req).do(event => { if (event instanceof HttpResponse) { this.cache.put(req, event); } }); return Observable.concat(maybeCachedResponse, networkResponse); }}
https://angular.io/guide/http#caching