iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0

在上一篇中我們講到了 DI ,這篇要來介紹 Effect 中的 DI 要如何透過 Layer 管理相依性

所以為什麼需要管理相依性,我們來講個例子,你設計了一個專門按下搖控器 (RemoteControl) 上的電源的程式,然而搖控器需要裝電池 (Battery) 才能運作

於是你的程式就有了以下的相依關係

https://ithelp.ithome.com.tw/upload/images/20250926/20111802ODtfz8E7Y1.png

轉成程式碼就是這樣

class Battery extends Effect.Service<Battery>()("Battery", {
  succeed: {
    powerLevel: 100
  }
}) {}

class RemoteControl extends Effect.Service<RemoteControl>()("RemoteControl", {
  effect: Effect.gen(function*() {
    const battery = yield* Battery
    return {
      pressPowerButton: () =>
        battery.powerLevel > 0
          ? Effect.void
          : Effect.fail(new Error("out of bettery"))
    }
  })
}) {}

const program = pipe(
  Effect.gen(function * () {
    const control = yield * RemoteControl
    yield * control.pressPowerButton()
  }),
  Effect.provide(RemoteControl.Default),
  // 提供了 RemoteControl 後,會發現少了 Bettery ,於是要再提供必要的 Battery
  Effect.provide(Battery.Default)
)

Effect.runPromise(program)

(playground link)

像這樣,你的 service 其實也可以依賴於其它的服務,不過如果你每次都需要寫一堆 Effect.provide 不覺的很麻煩嗎?這時候就是 Layer 出場的時機了, Layer 可以幫助你預先做好一些 service 的組合,像是 Steam 上的組合包一樣

// 結尾叫 Live 算是 Effect 中的一個開發習慣,如果是給 production 用的 layer ,結尾就會是 Live
const MainLive = pipe(
  RemoteControl.Default,
  Layer.provide(Battery.Default)
)

const program = pipe(
  Effect.gen(function * () {
    const control = yield * RemoteControl
    yield * control.pressPowerButton()
  }),
  Effect.provide(MainLive),
)

(playground link)

話說你可能會想問,為什麼 service 間會有相依性要管理,一個比較常見的例子,是你建了一個用來存取資料的 service StorageAccessor ,而這個 service 底下的資料要放在哪邊,其實是由另一個 service Storage 決定的,這樣你就可以容易的抽換如何儲存,例如正式時使用檔案系統,測試時記憶體暫存

另外 Effect.Service 在建立 service 時其實可以指定預設相依的 layer 的

class RemoteControl extends Effect.Service<RemoteControl>()("RemoteControl", {
  // 省略
  // 像這樣就可以指定預設相依的 layer
  dependencies: [Battery.Default]
}) {}

這樣 RemoteControl.Default 的這個 layer 就會預設已經有 Layer.provide(Battery.Default) 而可以直接使用了,可以到 playground 試看看

下一篇是第二篇的實戰分享,我們來寫個簡單的爬蟲看看吧

Reference


上一篇
10. Effect 的 dependency injection:打造可抽換的模組
系列文
Effect 魔法:打造堅不可摧的應用程式12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言