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 不透明类型 二叉树 代码组织 任务调度 优先级 使用服务 依赖注入 依赖管理 值语义 入门教程 最佳实践 最小堆 函数式编程 函数组合 前端 前端开发 副作用 副作用控制 可视化 可组合性 可维护性 可访问性 命令行 响应过滤 多个错误 实现 实践指南 层 层依赖 层组合 工具链 并发控制 应用架构 延迟执行 开发技巧 开发教程 开源 异步处理 异步操作 异步编程 性能优化 手写系列 排序 接口设计 插件开发 数据结构 数据获取 数据解码 数据验证 无限滚动 日历 日志分析 服务 服务依赖 服务定义 服务实现 服务提供 测试 源码分析 状态管理 环境变量 生成器 离线支持 程序分离 算法 类型安全 类型定义 类型推断 类型系统 类定义 线性代码 组合 翻译 自动化 自定义错误 表单验证 记忆化 设计模式 语义化 运维 运行时验证 部分应用 配置 配置变量 配置服务 配置管理 重构 错误处理 错误定义 错误恢复 项目设置
441 words
2 minutes
[使用生成器进行组合] 01. gen: 使用 Effect 编写线性代码
随着我们向 pipe 添加更多步骤,代码开始变得不太易读。
const main = fetchRequest.pipe(
Effect.filterOrFail(
(response) => response.ok,
() => new FetchError()
),
Effect.flatMap(jsonResponse),
Effect.catchTags({
FetchError: () => Effect.succeed("Fetch error"),
JsonError: () => Effect.succeed("Json error"),
})
);我们从简单的 if 检查,变成了看起来可怕的带有两个参数和更多代码行的 filterOrFail。
不要害怕!Effect 中有一个解决方案叫做 Effect.gen:
const main = Effect.gen(function* () {
const response = yield* fetchRequest;
if (!response.ok) {
return yield* new FetchError();
}
return yield* jsonResponse(response);
});如果你仔细观察,这与普通的 async/await TypeScript 函数非常相似:
const fetchRequest = () => fetch("https://pokeapi.co/api/v2/pokemon/garchomp/");
const jsonResponse = (response: Response) => response.json();
const main = async () => {
const response = await fetchRequest();
if (!response.ok) {
throw new FetchError();
}
return await jsonResponse(response);
};采用这种方式并进行以下更改:
将
async替换为Effect.gen将箭头函数
() =>替换为生成器函数function* ()将
await和throw替换为yield*
const main = async () => {
const response = await fetchRequest();
if (!response.ok) {
throw new FetchError();
}
return await jsonResponse(response);
};
// 👆 找出差异 👇
const main = Effect.gen(function* () {
const response = yield* fetchRequest;
if (!response.ok) {
return yield* new FetchError();
}
return yield* jsonResponse(response);
});生成器的工作原理
使用 Effect 时无需学习如何工作的细节。实际上,这只是一个实现细节。
作为参考,Effect.gen 使用了一个名为生成器函数的 JavaScript 特性。
这与迭代器协议结合使用,允许 Effect 在函数的每一步跟踪错误和成功。
对我们而言,这是一种编写更简洁、更美观的 Effect 代码的便捷方式,同时保持错误跟踪的所有好处。
我建议在大多数用例中优先使用
Effect.gen而不是pipe。这也是我在代码中的做法 💁🏼♂️
从现在开始,我们将尽可能使用 Effect.gen 而不是 pipe。
[使用生成器进行组合] 01. gen: 使用 Effect 编写线性代码
https://0bipinnata0.my/posts/course/effect-beginners-complete-getting-started/gen-composition-using-generators/01-gen-write-linear-code-with-effect/