Categories
Tags
Ai 生成 API学习 API简化 api请求 API调用 best-practices Blogging Caching catchTag catchTags class CLI Config context Context Context.Tag CSS Customization Demo development DocC Docker dual API Effect effect Effect.Service Effect.succeed Example extension ffmpeg filterOrFail flatMap Fuwari gen generator grep hooks HTML HTTP响应 IDE自动补全 iOS javascript JavaScript Javascript Layer.effect Layer.provide Layers Linux Markdown Mock n8n Next.js ParseError pipe pokemon PostCSS process.env progress Promise promise provideService PWA react React React Hook Form React Query React Router react-native Scheduler Schema Schema.Class security Service Worker Services SSR state-management suspense Tagged Errors TaggedError TanStack Query TanStack Start tips tryPromise tsconfig TypeScript typescript Video VS Code vscode Web API Web Development yield yt-dlp Zod 不透明类型 二叉树 代码组织 任务调度 优先级 使用服务 依赖注入 依赖管理 值语义 入门教程 最佳实践 最小堆 函数式编程 函数组合 前端 前端开发 副作用 副作用控制 可视化 可组合性 可维护性 可访问性 命令行 响应过滤 多个错误 实现 实践指南 层 层依赖 层组合 工具链 并发控制 应用架构 延迟执行 开发技巧 开发教程 开源 异步处理 异步操作 异步编程 性能优化 手写系列 排序 接口设计 插件开发 数据结构 数据获取 数据解码 数据验证 无限滚动 日历 日志分析 服务 服务依赖 服务定义 服务实现 服务提供 测试 源码分析 状态管理 环境变量 生成器 离线支持 程序分离 算法 类型安全 类型定义 类型推断 类型系统 类定义 线性代码 组合 翻译 自动化 自定义错误 表单验证 记忆化 设计模式 语义化 运维 运行时验证 部分应用 配置 配置变量 配置服务 配置管理 重构 错误处理 错误定义 错误恢复 项目设置
821 words
4 minutes
Effect 入门教程:4.控制副作用 - 像值一样处理 Effect
让我们退一步思考。console.log 有什么问题?为什么 effect 的急切执行是不好的?我们从 effect 增加的复杂性中获得了什么好处?
我们的目标是控制任何 effect,就像我们控制值一样:
- 将 effect 存储到变量中
const value = 10; // ✅
const value = console.log("Hello"); // ⛔️- 重构 effect 而不改变程序的含义
const main = () => {
// ...
console.log("Hello"); // ⛔️ 如果你把这个移出去,`main` 就改变了,它不再打印了!
// ...
}- 使它们具有确定性(易于测试)
/// ✅ 用相同的 `n` 调用这个函数总是给出相同的结果
const main = (n: number) => n * 2;
/// ⛔️ 我们如何测试这个?
const main = () => {
makePayment();
}我们所说的 “effect” 是指修改系统中某些内容的操作:
- 写入数据库(修改存储的数据)
- 打开弹窗(修改 UI)
- 在控制台打印(修改控制台状态)
const print = console.log("Hello");print 并没有存储日志操作。console.log 已经”做了”某些事情,它只是返回了空值(void)。
如果 print 只是描述*“将要在控制台打印的某些内容”*,那就太好了。
这将允许我们重用 print,将其存储到数组中,作为函数参数传递,这些都是像 console.log 这样的语句无法做到的:
const print: Print = // 想象 `Print` 存储"将要在控制台打印的某些内容"
// ✅ 我们可以将"打印"存储在数组中
const printingArray = [print, print, print];
// ✅ 我们可以将"打印"传递给函数
const printIfTrue = (check: boolean, toPrint: Print) => {
if (check) {
toPrint.run(); // 👈 这里是我们实际在控制台打印的地方
}
}
// 👇 `Print` 是一个值
printIfTrue(true, print);这在 console.log 中是无法做到的:
const printingArray = [
console.log("Hello"),
console.log("Hello"),
console.log("Hello"),
];
const printIfTrue = (check: boolean, toPrint: any) => {
/// ...
};
printIfTrue(true, console.log("Hello"));猜猜运行这段代码会发生什么?
每次我们定义 console.log 时,打印操作就会被执行。这是因为 console.log 是急切的:“定义”和”执行”之间没有区别。
当你输入 console.log 的那一刻,打印就被执行了。
想象一下,如果不是 console.log 而是 makePayement 😳
如何控制 effect
我们可以通过将 console.log 包装到函数中来”控制”它:
const print = () => console.log("Hello");这使得 console.log 成为一个值。因此我们可以像之前使用 Print 一样使用它:
// 👇 通过将 effect 包装到函数中将其转换为值
type Print = () => void;
const print: Print = () => console.log("Hello");
// ✅ 我们能够再次将"打印"视为值
const printingArray = [print, print, print];
const printIfTrue = (check: boolean, toPrint: Print) => {
if (check) {
toPrint();
}
}
printIfTrue(true, print);这样可以工作!它只会打印一个 Hello,这是由执行 printIfTrue 引起的:
这是 effect 中几乎所有内容的关键方面:
import { Console } from "effect";
const print = Console.log("Hello");
const printingArray = [print, print, print];
const printIfTrue = (check: boolean, toPrint: Effect<void>) => {
if (check) {
Effect.runSync(toPrint);
}
}
printIfTrue(true, print);Effect 允许控制 effect 并将它们视为值。
通过使用值而不是语句,我们重新获得了组合、重构和测试的能力。
再次强调,Effect 只是描述你的程序将要做什么。你需要显式地运行它才能发生任何事情。
Effect 入门教程:4.控制副作用 - 像值一样处理 Effect
https://0bipinnata0.my/posts/course/effect-beginners-complete-getting-started/setting-up-the-project/controlling-effect-like-values/