Angular service 詳解

小師太發表於2018-04-18

Angular為什麼需要service

  1. 元件應該是專注於展示層,所以需要service來獲取資料和儲存資料。
  2. 元件之間的通訊需要service來協助完成。

眾所周知,angular中service採用的是依賴注入,那什麼是依賴注入呢?

依賴注入(DI)是一種設計模式

為什麼需要依賴注入

從一個小例子說起

export class Car {

  public engine: Engine; // 引擎
  public tires: Tires; // 輪胎

  constructor() {
    this.engine = new Engine();
    this.tires = new Tires();
  }
}

//如果更換了引擎的建構函式,要傳入氣缸數,建構函式則要跟著改
  constructor() {
    this.engine = new Engine(12);
    this.tires = new Tires();
  }


複製程式碼

上面建立了一個汽車類,但是這個類完全沒有健壯性。假如引擎的建構函式改變了,構建引擎的時候需要傳一個引數,我們就得去汽車類裡面改變new Engine()這個使用。如果僅僅是需要改兩個地方可能還能接受,但是如果引擎類還依賴別的零件,這麼一層層的依賴關係,其中一個建構函式要發生改變了,可能會導致一連串的改變,會導致寫出來的程式碼完全沒有可維護性。輪胎也是如此,不同的汽車需要不同的輪胎,那麼像上述這麼寫就不太靈活,沒有通用性可言。

所以這樣就需要依賴注入

export class Car {
    constructor(public engine: Engine, public tires: Tires) { }
    }

let car = new Car(new Engine(), new Tires());
複製程式碼

這樣 engine和tire 和car類就是分離的,只要你是傳入的引擎和輪胎是滿足要求的,那麼這個car就是okay的。

class Engine2 {
  constructor(public cylinders: number) { }
}

// 如果需要一個12缸的引擎, 這樣我們完全不用動car類。
let bigCylinders = 12;
let car = new Car(new Engine2(bigCylinders), new Tires());
複製程式碼

依賴注入這種模式也為編寫測試用例提供了方便,在測試car類的時候,你不必去關係輪胎細節,只要給出一個可用的輪胎就行。

上面解釋了依賴注入是什麼,以及為什麼需要依賴注入。就是一個類從外界接受他所需要的依賴關係,而不是自己去創造它們。但是對於消費者,問題又來了。想要一輛車,就必須得有一個工廠來組裝出一個車

import { Engine, Tires, Car } from './car';

export class CarFactory {
  createCar() {
    let car = new Car(this.createEngine(), this.createTires());
    car.description = 'Factory';
    return car;
  }

  createEngine() {
    return new Engine();
  }

  createTires() {
    return new Tires();
  }
}
複製程式碼

這個模式看來起似乎沒有問題,但是這只是簡化的依賴,類似的引擎工廠類, 輪胎工廠類,相互呼叫,相互依賴,這會形成一個不可維護的?️

這個時候就需要一個依賴注入框架了。這個框架有一個叫注入器的東西,需要一個Car時, 只需要

let car = injector.get(Car);
複製程式碼

這樣消費者也不用去維護生產car的工廠類。並且car類本身也不管輪胎,引擎怎麼來的。皆大歡喜。

angular中依賴注入模式

angular中採用的是分層依賴注入

angular的應用程式是一個元件樹,每一個元件例項化都有自己的注入器providers。

Angular service 詳解

元件在找service的時候會一直向上冒泡尋找,直到找到根元件AppComponent還沒有找到的時候就會報錯。

這樣設計的好處:

  1. 便於元件之間的通訊。頂層一點的元件可以統一控制多個子元件的對同一個資料的操作。
  2. 增加複用。可以抽出多個底層元件複用的service寫在上層元件中。


angular中service的小知識

  1. 生成一個module的service。 ng g service test --module=app
  2. src/app/test.service.ts
    
    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class TestService {
      constructor() { }
    }
    複製程式碼
  3. 採用 @Injectable()裝飾器,這個東西告訴angular這個服務類可能本身注入了依賴,
  4. 元件本身是不管服務內部怎麼運作。
  5. service是必須通過providers注入。
  6. 是可以在服務的建構函式中呼叫一些業務函式 ,但不是最佳實踐。
  7. 服務在app內是單例的。


相關文章