iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 7
0
Modern Web

用Angular打造完整後台系列 第 7

day07 共用service(一)

簡述

說明會有哪些常見的服務是所有組件都會用的。

功能

開發過程中會有幾種服務是必然用到的。

  • logger.service.ts
  • web.service.ts
  • data.service.ts
  • user.service.ts
  • login.service.ts

檔案結構

-src
  |-app
    |-app.component.css
    |-app.component.html
    |-app.component.ts
    |-app.module.ts
    |-service
        |-logger.service.ts
        |-web.service.ts
        |-data.service.ts
        |-user.service.ts
        |-login.service.ts

實作

(一) LoggerService

在開發過程中,為了確保後端送來的值以及前端送去的值,
都是要符合API格式去定義的。

為了查驗,多半會在傳接值的部分印log出來看,
但是在系統上線後,這些log都必須拿掉
避免營運過程中有心人士看到並做不必要的事情。

environments:

專案預設有個 src/environments 資料夾,
是Angular用來動態切換環境的。

//environment.ts
export const environment = {
  production: false,
  logger: true
};
//environment.prod.ts
export const environment = {
  production: true,
  logger: false
};

之後系統上線後改參數就可統一拿掉。

一般編譯程式 npm start 會讀取到 environment.ts
如果是 npm build --prod
則build出來的網站會讀取environment.prod.ts
所以上線時就會看不到logger。

--

logger.service.ts

import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class LoggerService {
  private logger = environment.logger;

  log(msg: string) {
    if (this.logger) {
      console.log(msg);
    }
  }

  error(msg: string) {
    if (this.logger) {
      console.error(msg);
    }
  }

  print(index: string, msg: any) {
    if (this.logger) {
      console.log(index, msg);
    }
  }
}

在需要印log地方,寫上

this.logger.print("response", res)

(二) WebService

通常為了跟後端傳值與接值,會做全域型的service來提供
給所有需要資料傳送的功能模塊使用。

與後端做連接的部分,
因目前暫用json-server當 Database
所以API格式是RESTful。

web.service.ts

import { Injectable } from "@angular/core";
import { HttpClient, HttpHeaders } from "@angular/common/http";
import { Observable } from "rxjs/internal/Observable";
import { of } from "rxjs/internal/observable/of";
import { catchError, tap } from "rxjs/operators";
import { LoggerService } from "./logger.service";

@Injectable({
  providedIn: "root"
})
export class WebService {
  headers: HttpHeaders;

  constructor(private http: HttpClient, private logger: LoggerService) {}

  setHeaders(token: string) {
    this.headers = new HttpHeaders().set("Authentication", token);
  }

  getF<T>(url: string): Observable<T[]> {
    return this.http.get<T[]>(url, { headers: this.headers }).pipe(
      tap(res => this.logger.print("response", res)),
      catchError(this.handleError)
    );
  }

  postF<T>(url: string, obj: T): Observable<T> {
    return this.http.post<T>(url, obj, { headers: this.headers }).pipe(
      tap(res => this.logger.print("post", res)),
      catchError(this.handleError)
    );
  }

  delF<T>(url: string): Observable<T> {
    return this.http.delete<T>(url, { headers: this.headers }).pipe(
      tap(res => this.logger.print("del", res)),
      catchError(this.handleError)
    );
  }

  putF<T>(url: string, obj: T): Observable<T> {
    return this.http.put<T>(url, obj, { headers: this.headers }).pipe(
      tap(res => this.logger.print("put", res)),
      catchError(this.handleError)
    );
  }

  patchF<T>(url: string, obj: T): Observable<T> {
    return this.http.patch<T>(url, obj, { headers: this.headers}).pipe(
      tap(res => this.logger.print("patch", res)),
      catchError(this.handleError)
    );
  }

  private handleError(error: Response | any): Observable<any> {
    console.error(`${error.status}`);
    return of(null);
  }
}

最後面的handleError網上很多版本,
但是建議即使遇到錯誤,還是需送回一個空值回來。

實務上的流程都會在一開始連接的時候就要設定token,
並且每次的請求都要夾帶token。


(三) 補充說明

當service裡有以下宣告時:

@Injectable({
  providedIn: 'root'
})

代表它是整個系統唯一實體,
所以沒有在app.module.ts裡面註冊也沒關係。


範例碼

https://stackblitz.com/edit/ngcms-service


上一篇
day06 json-server 模擬與 Model 建置(二)
下一篇
day08 共用service(二)
系列文
用Angular打造完整後台30

尚未有邦友留言

立即登入留言