iT邦幫忙

2025 iThome 鐵人賽

DAY 10
0

在這篇裡,我們要來介紹 Effect 最強大的功能,排程還有錯誤重試

重覆執行

有時你可能需要重覆執行一段程式碼,平常你可能會使用迴圈做,如果還要加上定時的話,你可能會選擇使用 setInterval 或是 setTimeout ,例如你需要使用 API 定時的同步一下資料的最新狀態

那在 Effect 中呢?我們先來看沒有定時的

pipe(
  doSomething()
  Effect.repeatN(2),
  Effect.runPromise
)

上面的 code 你可以在 playground 試試

這看起來直覺的你會認為應該是執行兩次,不過實際上是 3 次,這個是我覺得 Effect 中一個有點怪的設計,它的 repeat 系列的 function 的執行其實是「加」上去的,如果你指定兩次,那不論如何它會先執行一次後,才開始執行你指定的兩次

那如果要定時呢?我們可以用更強大的 Effect.repeat

import { Effect, Schedule } from 'effect'
pipe(
  doSomething()
  Effect.repeat(Schedule.spaced('1 second')),
  Effect.runPromise
)

同樣的可以到 playground 中測試,這個會在執行一次後,開始無限的間隔一秒鐘執行, Effect 中可以用字串指定單位是一個我很喜歡的設計,因為這樣就不會搞錯單位了

那如果加上次數的限制呢?有兩種做法

import { Effect, Schedule } from 'effect'
pipe(
  doSomething()
  Effect.repeat({
    schedule: Schedule.spaced('1 second'),
    times: 3,
  }),
  Effect.runPromise
)

(playground link)

import { Effect, Schedule } from 'effect'
pipe(
  doSomething()
  Effect.repeat(Schedule.intersect(Schedule.spaced("1 second"), Schedule.recurs(3))),
  Effect.runPromise
)

(playground link)

到這邊你可能有注意到, Effect 中的 Schedule 其實可以組合出非常多種不同的重覆條件,因為篇幅,這邊就不一一介紹了,但 Effect 還可以設定出以下的重試條件:

而且這些策略還可以使用 Schedule.intersectSchedule.union 進行各種組合,有興趣可以去看官方的文件

另外需要注意的是, Effect 重覆執行的過程中,如果有發生錯誤的話是會停止的,這點跟 setInterval 並不同,如果你需要做到就算碰到錯誤也要重覆執行下去,會需要用 Effect.ignore 忽略掉 Effect 的結果

錯誤重試

前面講的是一般的重覆執行,這邊來來的是錯誤時的重試,在現在 AI 的時代,如果你的程式的核心是使用 AI 的 API 的話,當 AI 沒有回應時,你應該會想要重試吧,畢竟如果不重試就執行不下去了,這時候就可以用到 Effect.retry

import { Effect, pipe } from 'effect'

let count = 0

pipe(
  Effect.try(() => {
    // 這個 console log 可以讓你知道真的有在重試
    console.log('attempt', ++count)
    if (Math.random() > 0.5) {
      throw new Error('oh no')
    } else {
      return 42
    }
  }),
  Effect.retry({
    times: 3
  }),
  Effect.runPromise,
)

(playground link)

可以試著稍為改動一點 code ,讓它重覆跑看看,實際看看重試的效果。Effect.retry 就像是在失敗時重覆執行的 Effect.repeat ,它也可以接受 schedule 這個參數,也就是說你同樣的可以控制它重試幾次,重試間要等多久等等

在經過了前一篇的實戰分享,加上這篇的 Effect.repeatEffect.retry ,不知道你有沒有開始感受到,就如同一開始所說的, Effect 在寫的時候,是先設計好流程,決定好要如何處理資料後再開始執行, Effect 提供了很多的積木讓你去設計流程,你只需要專注在核心的資料處理即可,這篇正好是第 10 篇了,如果你對於這個系列有什麼想法的話,歡迎讓我知道

在下一篇,我們要來介紹可以讓程式進一部的 decouple 與讓測試變的更容易的 dependency injection

Reference


上一篇
8. Effect 實戰分享 1 :資料清理
系列文
Effect 魔法:打造堅不可摧的應用程式10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言