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 不透明类型 二叉树 代码组织 任务调度 优先级 使用服务 依赖注入 依赖管理 值语义 入门教程 最佳实践 最小堆 函数式编程 函数组合 前端 前端开发 副作用 副作用控制 可视化 可组合性 可维护性 可访问性 命令行 响应过滤 多个错误 实现 实践指南 层 层依赖 层组合 工具链 并发控制 应用架构 延迟执行 开发技巧 开发教程 开源 异步处理 异步操作 异步编程 性能优化 手写系列 排序 接口设计 插件开发 数据结构 数据获取 数据解码 数据验证 无限滚动 日历 日志分析 服务 服务依赖 服务定义 服务实现 服务提供 测试 源码分析 状态管理 环境变量 生成器 离线支持 程序分离 算法 类型安全 类型定义 类型推断 类型系统 类定义 线性代码 组合 翻译 自动化 自定义错误 表单验证 记忆化 设计模式 语义化 运维 运行时验证 部分应用 配置 配置变量 配置服务 配置管理 重构 错误处理 错误定义 错误恢复 项目设置
471 words
2 minutes
[Effect Layers] 06. 多次提供同一层
多次提供同一层
https://github.com/typeonce-dev/effect-getting-started-course
你可能注意到了一些奇怪的事情:我们在组合 MainLayer 时使用了两次 PokeApiUrlLive。
const MainLayer = Layer.mergeAll(
PokeApi.Live,
PokemonCollection.Live,
BuildPokeApiUrl.Live.pipe(Layer.provide(PokeApiUrl.Live)),
PokeApiUrl.Live,
);这是一个问题吗?层会被创建多次吗?
TIP层的记忆化
这完全不是问题,因为Effect中的层是记忆化的。这意味着每个层只会被创建一次,每次都会提供相同的实例。
这使得组合层变得更加方便。
实际上,在 Live 内定义 Layer 时直接提供所需的依赖关系是一个好的实践:
BuildPokeApiUrl.ts
export class BuildPokeApiUrl extends Context.Tag("BuildPokeApiUrl")<
BuildPokeApiUrl,
({ name }: { name: string }) => string
>() {
static readonly Live = Layer.effect(
this,
Effect.gen(function* () {
const pokeApiUrl = yield* PokeApiUrl;
return ({ name }) => `${pokeApiUrl}/${name}`;
})
).pipe(
// 在 `Live` 内直接提供依赖层
Layer.provide(PokeApiUrl.Live)
);
}有了这些,MainLayer 只需要一个简单的 mergeAll 来包含运行程序所需的所有层:
index.ts
const MainLayer = Layer.mergeAll(
PokeApi.Live,
PokemonCollection.Live,
BuildPokeApiUrl.Live,
PokeApiUrl.Live
);IMPORTANTEffect 组合模型的强大之处
这就是Effect组合模型的全部力量!我们可以通过更改一行代码来交换层。这允许轻松地混合和组合不同的实现,同时保持完全的类型安全。
此外,我们可以再次专注于单个服务实现,而不必担心其依赖关系或错误。
NOTE开发体验优势
一切都在最后收集和提供。对代码库进行更改变得更容易,因为我们不需要阅读或理解所有内容,而是可以专注于单个服务。
维护应用程序也变得更容易,因为每个破坏性更改都会导致类型问题,TypeScript编译器会指导我们在需要的地方解决。
这就是完全的类型安全!这是不归路:一旦你理解了这个模型有多强大,你就再也不会回头了!