終於寫到這步,好懶得寫底層,但是還是寫了,考量以後可能有驗證問題還是統一寫比較好。
以下統一設定了http 標頭,方便未來加入token驗證,錯誤回報也統一在 handleError 處理,handleResponse 目前很單純,不過未來如果在API發送成功後,有特殊規格的話可以在這處理。
import { Injectable } from '@angular/core';
import { ApiResponse } from '../interface/api.interface';
import { catchError, filter, Observable, throwError } from 'rxjs';
import { environment } from 'src/environments/environment';
import { API, COMMON, HTTP_METHOD } from '../global-constants.const';
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(
private http: HttpClient
) { }
private getHTTPHeaders(): HttpHeaders {
const result = new HttpHeaders({
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + sessionStorage.getItem(COMMON.TOKEN),
});
return result;
}
private handleResponse = (response: ApiResponse<unknown>): boolean => {
return response.success;
}
private handleError = (error: HttpErrorResponse) => {
let errorMessage = 'An unknown error occurred';
// 客戶端或網路錯誤
if (error.error instanceof ErrorEvent) {
console.error('Client-side error:', error.error.message);
errorMessage = `Client-side error: ${error.error.message}`;
}
// 伺服器端錯誤
else {
console.error(`Backend returned code ${error.status}, body was:`, error.error);
// 根據不同的 HTTP 狀態碼處理錯誤訊息
switch (error.status) {
case 400:
errorMessage = 'Bad request. Please verify your inputs.';
break;
case 401:
errorMessage = 'Unauthorized. Please log in again.';
break;
case 403:
errorMessage = 'Forbidden. You don’t have permission to access this resource.';
break;
case 404:
errorMessage = 'Not found. The requested resource does not exist.';
break;
case 500:
errorMessage = 'Internal Server Error. Please try again later.';
break;
default:
errorMessage = `Unexpected error: ${error.status}. Please try again later.`;
}
}
// 回傳可讀性高的錯誤訊息
return throwError(() => new Error(errorMessage));
}
/**
* call HTTP 主要方法
* @param method http method
* @param requestParams request body
* @param api api url
*/
request(method: string, requestParams: any, api: string): Observable<ApiResponse<any>> {
const httpHeaders = this.getHTTPHeaders();
const url = `${environment.DEFAULT_IP}/${api}`;
console.log('url', url);
switch (method) {
case HTTP_METHOD.GET:
return this.http
.get<any>(url, { headers: httpHeaders, params: requestParams })
.pipe(filter(this.handleResponse), catchError(this.handleError));
case HTTP_METHOD.DELETE:
return this.http
.delete<any>(url, { headers: httpHeaders, params: requestParams })
.pipe(filter(this.handleResponse), catchError(this.handleError));
case HTTP_METHOD.POST:
return this.http
.post<any>(url, requestParams, { headers: httpHeaders })
.pipe(filter(this.handleResponse), catchError(this.handleError));
case HTTP_METHOD.PATCH:
return this.http
.patch<any>(url, requestParams, { headers: httpHeaders })
.pipe(filter(this.handleResponse), catchError(this.handleError));
case HTTP_METHOD.PUT:
return this.http
.put<any>(url, requestParams, { headers: httpHeaders })
.pipe(filter(this.handleResponse), catchError(this.handleError));
default:
return this.http
.get<any>(url, { headers: httpHeaders, params: requestParams })
.pipe(filter(this.handleResponse), catchError(this.handleError));
}
}
}
串起來的效果