# 使用 Effect 提升前端應用程式的穩定性與可維護性 - 彭勝宇 {%hackmd @JSDC-tw/B1loEcwJZl %} ###### tags: `JSDC2025` Slido:https://app.sli.do/event/pG5n1iyWYfa6TEpoLA7DA6 Effect 的官網: https://effect.website 講者寫的教學文章: https://ithelp.ithome.com.tw/users/20111802/ironman/8800 互動式的 Effect 教學: https://effect.kitlangton.com 簡報: - [web 版](https://dansnow.github.io/talks/2025-11-29-jsdc/) - [pdf 版](https://github.com/DanSnow/talks/blob/main/slides/2025-11-29-jsdc/%E4%BD%BF%E7%94%A8%20Effect%20%E6%8F%90%E5%8D%87%E5%89%8D%E7%AB%AF%E6%87%89%E7%94%A8%E7%A8%8B%E5%BC%8F%E7%9A%84%E7%A9%A9%E5%AE%9A%E6%80%A7%E8%88%87%E5%8F%AF%E7%B6%AD%E8%AD%B7%E6%80%A7%20-%20Slidev.pdf) > 開始做筆記 Effect 很少人聽過,更不用說用過的人了 2020 出,2024 - 2025 12K Starts 講者在發哥 David Peng https://github.com/danshow ## Type-Safe Error Handling Demo Code 潛在的錯誤 ```ts= function getData(id: string) { const r = await fetch(`/items/${id}`); // Fetch 網路問題 return r.json() // JSON 型別不明 } ``` 嘗試 Handling, 程式碼大暴增,這裡只列部分 slide ```ts= invariant(id.length > 0, 'id 長度'); throw new Error(); ``` - 複雜度 ### Effect Type ```ts= // Original: Effect<A, E, R> Effect<Success, Error, Requirements> ``` 設置檢查點 上述範例改寫 ```ts= Effect.fn('fetchDetail')(function *(id: string) { const res = yield* Effect.tryPromise({ try: () => fetch(`/items/${id}`); catch: () => throw }) }); ``` > 重新發現 Generator 的好 async + await 放到 JS Runtime generator 放到 code 的外面,丟出去然後從 yield 拿回來 ```ts= function *fetchDetail() { const a = yield *getXXX(); } Effect.run( fetchDetail(), (error) => handleError(error) ); ``` Promise 的短處: 1. 無法標示可能發生的錯誤 2. API 設計 -> 錯誤碼多,non 200 + network ### Schema 定義型態 ```ts= const ItemSchema = Schema.Struct({ id: Schema.String, }); type ItemDetail = typeof ItemSchema.Type; ``` ## Effect 畫藍圖 ```ts= pRetry( async () => { const result = await flaskyAPI(); }, { retries: 3, minTimeout: 500, factor: 2 } ) ``` Effect ```ts= Effect.tryPromise( ), Effect.retry({ times: 3, }) ``` ```ts= Effect.all( [ fetchUser(1), ], { concurrency: 'unbounded' } ) ``` Q&A: 包起來,要怎麼平行地處理 yield? Effect runtime 也可以處理 > function programming 的延伸 強調 "要做什麼",自由組裝 ### Dependencies Injection `Effect.provideService` ### Demo Trello - 從[TypeSense](https://typesense.org/)不同抓取條件 - 一次抓多個 - 大量平行請求 - 網路不穩定處理 背後會幫你組合起來 案例分享:瀏覽器資料遷移 - 本機資料與 Server 資料會重複生成很多 - 累積了不少資料 - 決定一次將 Client 資料傳上 Server,資料量過大 `withProgressRecord` 追蹤資料走向 `Effect.addWith` 一次收集全部 ## 導入 Effect 遇到的問題 - Learning Curve - New Concepts to be used to - Resolve: - From small side project - Code Review to share knowledge - 擅長 - 複雜錯誤 - 異步 - Retry - Concurrency - 資源管理 - 依賴注入 - 類型安全 # Q & A - 有互動教學:https://effect.kitlangton.com 午安,想知道 Effect 跟 RxJS 有什麼差異呢? - RxJS 處理 Steam 前端資料容易被後端資料架構限制,要怎麼導入 - 先用熟悉的方式 佔空間? - 看你怎麼使用 - 開發電商會有固定流程 - 若遇到複雜狀況可以考慮 vs fp-ts - fp-ts 作者加入 Effect 了! Effect 推薦使用 fp 嗎?class - 的確鼓勵使用 fp,除了部分 class > 聊天區 --- {%hackmd @JSDC-tw/jsdc2025_sponsor %}