@ exodus/ 依赖注射
这是控制容器的基本倒置,它解决了依赖性图表,将所有节点都即时化. 如果你想用它,如果你正在缝合 一个应用程序 从几十个不同的模块, 和你的强制定义 依赖DAG 开始变得无法管理.
有很多复杂的反转 控制容器在那里,例如. 无效, (中文(简体) ), 阿维利克斯还有其他 他们可能很棒。 有一天,我们可能会转向它们, 但此时,它们已经过度杀伤, 它们提高认知负载 比绝对必要的。 这个库以高度有见地的方式执行一个简单的容器,几乎没有灵活性. 以下是依赖列表中的样本节点:
[
...,
{
id: 'harry',
dependencies: ['scar', 'dobby'],
factory: ({ scar, dobby }) => {
// Harry uses his scar to defeat dobby, or however that book goes
},
type: 'wizard', // optional
}
]
如所见:
- 每个节点都有全球独有的字符串
id。 。 。 . - 它列出其
dependencies作为字符串标识. - 它宣布
factory函数,它接收单个对象作为参数,命名选项映射 1:1 到 ids 在依赖性中列出 - 它宣布一个可选
type字段。 您可以用它查询节点的容器type是一个特定值.
容器会给出一个这样的节点列表,会给出所有实例. 就是这样!
使用量
宣布节点和边缘 让集装箱把一切都接通.
import createContainer from '@exodus/dependency-injection'
const createLogger =
(namespace) =>
(...args) =>
console(namespace, ...args)
const container = createContainer({ logger })
container.registerMultiple([
{
id: 'storage',
factory: createStorage,
},
{
id: 'assetsModule',
// the container will pass `({ logger })` to the factory
factory: createAssetsModule,
dependencies: ['logger'],
},
{
id: 'walletAccountsAtom',
factory: () =>
createInMemoryAtom({
defaultValue: { [WalletAccount.DEFAULT_NAME]: WalletAccount.DEFAULT },
}),
},
{
id: 'enabledWalletAccountsAtom',
// the container will pass `({ walletAccountsAtom })` to the factory
factory: createEnabledWalletAccountsAtom,
dependencies: ['walletAccountsAtom'],
},
{
id: 'blockchainMetadata',
factory: createBlockchainMetadata,
// the container will pass `({ assetsModule, enabledWalletAccountsAtom })` to the factory
dependencies: ['assetsModule', 'enabledWalletAccountsAtom'],
},
])
压倒性的依赖关系
容器在遇到重复的依赖标识时会抛出. 为测试目的, 使用覆盖旗
container.register({
id: 'balances',
override: true,
factory: () => ({ load: jest.fn() }),
})
container.resolve()
const {
storage,
assetsModule,
walletAccountsAtom,
enabledWalletAccountsAtom,
blockchainMetadata,
balances,
} = container.getAll()
可选依赖关系
可选的依赖关系可以通过附加后缀来请求 ?数字 :
container.register({
id: 'jediSurvivor',
factory: ({ lightsaber, theForce }) => {
if (lightsaber) {
// code has to make sure optionality is gracefully handled
return new InsaneLightsaberWiedlingJedi(lightsaber)
}
return new ThereIsOnlyTheForce(theForce)
},
dependencies: ['lightsaber?', 'theForce'],
})
注入样式
默认的依赖性作为命名选项被注入,这就是推荐的模式. 但是,如果您的使用大小写需要将依赖性作为位置参数注入,例如,如果您的工厂功能是 reselect 选择器,指定 injectDependenciesAsPositionalArguments: true 在容器一级通过建造器,或在单个节点一级。 见 实例 在测试.
已知问题/局限性
- 每个节点中只有一个被创建. 在99%的情况下,这是你想要的,但看到 杂项 以实例为例.
- 这种执行将若干概念概括为一个概念
id数字 :- 全球独有的软件包 ID, 由给定软件包导出, 例如 .
'analytics'联 合 国 分析 模块. - 全球独特性 接口 标识符,例如.
'analytics',它与具有某些方法并带有某些签名的物体相对应。 分析师们宣布dependencies数组编号. - 构建器选项名称,用于分析学的消费者,例如:.
constructor({ analytics })
- 全球独有的软件包 ID, 由给定软件包导出, 例如 .
将来我们可能会把这些分开, 但在短期内,我们选择了简单.
示例(无标题)
见 无头 作为真实世界的e2e实例,初始化了国际奥委会,并利用了 多个预处理器.
理由
请允许我模拟一下你的内部对话.
You见鬼! 后生是 1) 更多的动词, 2) 具有更高的认知负载 和 3) 通过使用ID而不是函数指针来打破Intellisense.
Container- 我听见了 我应改进这些帮我帮你) (中文(简体) ). 另一方面,我有几个优势随着您节点列表的增长而增长(例如Exodus浏览器扩展已经拥有了>100个节点). 我让你:
- 明确定义你的依赖关系.
- 停止手动管理即时命令 。 我会通过走 依赖图来解决问题.
- 统一即时模式和最佳做法.
- 验证一个节点是否接收所有已申报的依赖.
- 集中记录,出错处理,权限等内容. 这让你把密码弄干.
- 通过依赖树进行跟踪事件/数据传播.
- 可视化/打印/绘制依赖图.
- 自动插入 namespaced loggers, namespaced 存储实例, 以及节点特定配置 .
杂项( 仅实现过度)
检查出来 @ exodus/ 依赖性预处理器,使 config 财务报告和审定财务报表 logger 以上叙述的特殊情况.