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 不透明类型 二叉树 代码组织 任务调度 优先级 使用服务 依赖注入 依赖管理 值语义 入门教程 最佳实践 最小堆 函数式编程 函数组合 前端 前端开发 副作用 副作用控制 可视化 可组合性 可维护性 可访问性 命令行 响应过滤 多个错误 实现 实践指南 层 层依赖 层组合 工具链 并发控制 应用架构 延迟执行 开发技巧 开发教程 开源 异步处理 异步操作 异步编程 性能优化 手写系列 排序 接口设计 插件开发 数据结构 数据获取 数据解码 数据验证 无限滚动 日历 日志分析 服务 服务依赖 服务定义 服务实现 服务提供 测试 源码分析 状态管理 环境变量 生成器 离线支持 程序分离 算法 类型安全 类型定义 类型推断 类型系统 类定义 线性代码 组合 翻译 自动化 自定义错误 表单验证 记忆化 设计模式 语义化 运维 运行时验证 部分应用 配置 配置变量 配置服务 配置管理 重构 错误处理 错误定义 错误恢复 项目设置
525 words
3 minutes
[Effect Services] 02. Context:依赖注入
Context:依赖注入
TIP依赖注入模式
我们的目标是围绕”抽象接口”组织我们的代码库,每个接口仅定义我们 API 的签名。
然后根据环境(测试、开发、生产),我们构建并提供具体的实现。
这种模式称为依赖注入。
Effect 服务专为依赖注入而设计。不仅如此,Effect 还使依赖注入完全类型安全。
Effect 中的服务:Context
NOTEContext 工作原理
通用服务使用
Context定义。
Context实现为一个全局Map,按键存储服务实现。当我们提供具体实现时,Effect 从这个全局
Map中提取服务(全部类型安全)。
通常的做法是在与服务同名的文件中定义每个服务。因此我们为新服务创建一个新的 PokeApi.ts 文件。
我个人使用 Pascal 命名法为每个服务命名,在这个例子中是
PokeApi
我们首先使用简单的 interface 定义我们 API 的签名。这包含服务提供的所有方法:
PokeApi.ts
import { Effect, type ParseResult } from "effect";
import type { ConfigError } from "effect/ConfigError";
import type { FetchError, JsonError } from "./errors";
import type { Pokemon } from "./schemas";
export interface PokeApi {
readonly getPokemon: Effect.Effect<
Pokemon,
FetchError | JsonError | ParseResult.ParseError | ConfigError
>;
}手动定义
interface比较冗长。别担心,有更简洁的方法,现在请先忍耐一下。
基于这个 interface,我们使用 Context.GenericTag 创建服务:
- 我们传递一个键
string,用于在全局Map中标识服务("PokeApi")
import { Effect, Context } from "effect";
export interface PokeApi {
readonly getPokemon: Effect.Effect<
typeof Pokemon.Type,
FetchError | JsonError | ParseResult.ParseError | ConfigError
>;
}
export const PokeApi = Context.GenericTag<PokeApi>("PokeApi");给
interface和Context服务使用相同的名称(PokeApi)很方便。这允许通过单个导入将服务既作为类型又作为值导出和使用。
IMPORTANT可组合性的力量
这就是定义服务所需的全部内容。如您所见,我们还没有定义任何具体实现。尽管如此,我们已经可以开始使用该服务了。实现可以稍后定义。这就是可组合性和依赖注入的力量!
[Effect Services] 02. Context:依赖注入
https://0bipinnata0.my/posts/course/effect-beginners-complete-getting-started/effect-services/02-context-dependency-injection/