这个周末学习了一个新工具 Effect-TS
,打开我了写代码的新思路,现在迫不及待的分享给大家!
Effect-TS 的核心是一个名为 Effect
的数据结构,它封装了副作用(例如网络请求、文件操作等),并提供了类型安全的操作方式。Effect 的几个关键特性包括:
Produces a value of type number
│ Fails with an Error
│ │ Requires no dependencies
▼ ▼ ▼
Effect<number, Error, never>
首先可以通过以下命令安装 Effect-TS 到你的项目:
pnpm add effect
Effect-TS 同时提供了一个命令行工具 create-effect-app
,可以重新初始化一个新的项目:
pnpm create effect-app@latest
运行后,工具会引导你选择模板和配置 ESLint 等工具,生成一个预配置好的 Effect 项目!
初始化
import { Console, Effect } from "effect";
const main = Console.log("Hello, World!");
Effect.runSync(main);
这里 Console.log 是一个 Effect 操作,Effect.runSync 是同步执行 Effect 的方法。
pipe 是 Effect 库中用于流式组合操作的核心工具,它通过线性化的方式将 Effect 的操作符和函数连接起来,使代码更简洁、可读且符合函数式编程风格。
import { Effect } from "effect";
const program = Effect.succeed(42).pipe(
Effect.map((n) => n * 2),
Effect.map((n) => n + 10)
);
// 运行后得到:Effect<never, never, 94>
// 解释:42 先被 map 乘以 2 得到 84,再被 map 加上 10 得到 94
操作符(Operator)是指一类用于处理、转换或组合数据流(在这里是 Effect 值)的函数或方法。这些操作符通常以声明式的方式操作 Effect 对象,帮助开发者以函数式编程风格管理副作用、异步流程或复杂逻辑。
除了上面提到的 map
,还要很多类似数组的操作方法,flatMap
、zip
等等!
Effect.succeed(10)
.pipe(Effect.flatMap((n) => Effect.succeed(n + 5)));
// 结果:Effect<never, never, 15>
通常,我们需要和 pip 配合,将多个操作符组合起来
import { Effect } from "effect";
const program = Effect.succeed(10).pipe(
Effect.map((n) => n * 2),
Effect.flatMap((n) => Effect.succeed(n + 5)),
Effect.map((n) => `Result: ${n}`)
);
// 结果:Effect<never, never, "Result: 25">
Effect-TS 的结构化并发确保所有异步任务都能被正确管理。例如,运行多个并发请求:
import { Effect } from "effect";
const program = Effect.all([
getTodo(1),
getTodo(2),
getTodo(3)
]).pipe(
Effect.tap((todos) => Console.log(`Fetched todos: ${JSON.stringify(todos)}`))
);
Effect.runPromise(program);
Effect.all
并行执行多个 Effect,并在所有任务完成时返回结果。如果某个任务失败,Effect 会自动清理其他任务,避免资源泄漏。
Effect-TS 特别擅长处理异步逻辑。假设我们要从一个 API 获取数据,可以这样实现:
import { Effect, HttpClient } from "effect";
const getTodo = (id: number) =>
HttpClient.get(`/todos/${id}`).pipe(
Effect.andThen((response) => response.json)
);
const program = getTodo(1).pipe(
Effect.tap((data) => Console.log(`Fetched todo: ${JSON.stringify(data)}`)),
Effect.catchAll((error) => Console.log(`Error: ${error.message}`))
);
Effect.runPromise(program);
这段代码定义了一个 getTodo
函数,使用 HttpClient
发送 GET 请求。使用 pipe
组合操作,通过 Effect.andThen
解析 JSON 响应。使用 Effect.tap
打印结果,Effect.catchAll
捕获并处理错误。 最后通过 Effect.runPromise
异步执行程序。
Effect-TS 内置了强大的错误处理和重试机制。例如,我们可以为 API 请求添加重试和超时逻辑:
import { Effect, Schedule } from "effect";
const robustGetTodo = (id: number) =>
getTodo(id).pipe(
Effect.retry(Schedule.exponential("100 millis", 2).pipe(Schedule.upTo(3))),
Effect.timeout("1 second")
);
const program = robustGetTodo(1).pipe(
Effect.tap((data) => Console.log(`Success: ${JSON.stringify(data)}`)),
Effect.catchAll((error) => Console.log(`Failed: ${error.message}`))
);
Effect.runPromise(program);
这里 Effect.retry
使用指数退避策略重试最多 3 次。Effect.timeout
设置 1 秒超时,超时后自动中止请求。所有这些操作都是声明式的,代码清晰且易于维护。
❝相较于 VueUse 或 ahooks 返回的错误类型通常是 unknown 或泛型,需要我们手动处理类型断言或错误边界!
Effect-TS 不仅仅是一个核心库,它还有丰富的生态系统。感兴趣的小伙伴可以看这里
https://github.com/Effect-TS/effect?tab=readme-ov-file#monorepo-structure
生态
文章有限,我介绍了九牛一毛,感兴趣的同学可以看看文档:https://effect.website/docs
今天的分享就这些了,感谢大家的阅读,如果文章中存在错误的地方欢迎指正!
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有