在Angular 中, Pipe 就像WPF 中的coverter 般將接到的data 轉換為用作須要用的format顯示出來. 然而在front-end development 中, 從web service 接到的日期, 通常都被當成string 般處理. 若要須要轉成Date, 則需要透過interceptor 收到response, 利用regular expression 轉換成 Date 回傳出來. 在示範中, 會利用HTTP response 的JSON方法如下.json-interceptor.ts
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse, HttpErrorResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import 'rxjs/add/operator/map'; // https://github.com/angular/angular/blob/master/packages/common/http/src/xhr.ts#L18 const XSSI_PREFIX = /^\)\]\}',?\n/; /** * Provide custom json parsing capabilities for api requests. * @export * @class JsonInterceptor */ @Injectable() export class JsonInterceptor implements HttpInterceptor { /** * Custom http request interceptor * @public * @param {HttpRequest<any>} req * @param {HttpHandler} next * @returns {Observable<HttpEvent<any>>} * @memberof JsonInterceptor */ public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { if (req.responseType !== 'json') { return next.handle(req); } // convert to responseType of text to skip angular parsing req = req.clone({ responseType: 'text' }); return next.handle(req).map(event => { // Pass through everything except for the final response. if (!(event instanceof HttpResponse)) { return event; } return this.processJsonResponse(event); }); } /** * Parse the json body using custom revivers. * @private * @param {HttpResponse<string>} res * @returns{HttpResponse<any>} * @memberof JsonInterceptor */ private processJsonResponse(res: HttpResponse<string>): HttpResponse<any> { let body = res.body; if (typeof body === 'string') { const originalBody = body; body = body.replace(XSSI_PREFIX, ''); try { body = body !== '' ? JSON.parse(body, (key: any, value: any) => this.reviveUtcDate(key, value)) : null; } catch (error) { // match https://github.com/angular/angular/blob/master/packages/common/http/src/xhr.ts#L221 throw new HttpErrorResponse({ error: { error, text: originalBody }, headers: res.headers, status: res.status, statusText: res.statusText, url: res.url || undefined, }); } } return res.clone({ body }); } /** * Detect a date string and convert it to a date object. * @private * @param {*} key json property key. * @param {*} value json property value. * @returns {*} original value or the parsed date. * @memberof JsonInterceptor */ private reviveUtcDate(key: any, value: any): any { if (typeof value !== 'string') { return value; } if (value === '0001-01-01T00:00:00.000+0000') { return null; } const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})\.(\d{3})[+-](\d{4})$/.exec(value); if (!match) { return value; } return new Date(value); } }
app.module 叫用方法:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { JsonInterceptor } from '../json-interceptor'; @NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: JsonInterceptor, multi: true } ] })
Leave a Reply