2024 Clojure 状态调查中分享您的意见!

欢迎!请参阅关于页面以获取有关如何操作的更多信息。

+1

hi folks, 我正在尝试使用Integrant库进行状态管理。它在管理(启动/停止)服务器方面非常直观,但我在某个特定用例上感到困惑。

我想要使用Integrant来实例化和销毁一个对象。就像往常一样,我定义了defmethods init-key和halt-key!。问题是我想从init-key获得已初始化对象的引用。是否有惯用的方法来做这件事?我应该只让它在init-key期间在atom中可用吗?

(defmethod ig/init-key :my-space/my-key [_ opts]
  (let [account-id (:account-id opts)
        license-key (:license-key opts)]
    (MyObject. account-id license-key)))

;;How do I use the instantiated my object?

2 答案

+1

当你调用(ig/init config)时,它按照你的配置映射的依赖顺序调用ig/init-key,并返回一个字典,其中每个键都是定义的init-key之一。在你的例子中,它将返回{:my-space/my-key #<MyObject…>}。根据你的应用结构的创建方式,你可以把这个映射存储到一个变量或原子中,或者你可以将其作为参数传递给你的ring中间件,以便每个请求都有一个引用等。

要调用MyObject的方法,你将写入(.someMethod (:my-space/my-key system))

0

您可以将那个:my-space/my-key作为参数传递给另一个组件,该组件然后将接收到的MyObject实例。

例如,如果您在使用Integrant和Aero,它的样子可能是这样的

;; my_space.clj
(defmethod ig/init-key ::my-key [_ opts]
  (let [account-id (:account-id opts)
        license-key (:license-key opts)]
    (MyObject. account-id license-key)))

(defmethod ig/init-key ::other-key [_ {:keys [my-object]}]
  (println "Got object" my-object))

;; config.edn
{:ig/system
 {:my-space/my-key    {:account-id  1
                       :license-key 2}
  :my-space/other-key {:my-object #ig/ref :my-space/my-key}}}
我想在defmethod之外使用它。我想在普通函数中使用`MyObject`。
那么这将是Integrant的一个误用,你几乎完全打破了整个系统。你可以向这些普通函数提供一个额外的参数,它来自某个地方并且包含该对象,你可以在`::other-key`组件中创建这些函数作为闭包,你可以让它们成为协议的一部分,并从`::other-key`组件返回实现对象。所以,对于你的问题有解决方案,创建一个全局单例并不是一个好的选择。
我不确定我是否理解了关于"带有额外参数的普通函数...可以创建这些函数作为闭包"的解决方案。你能给我指一个例子吗?
每个函数都有一个调用者。您可以使用调用者传递额外参数的方法,将`MyObject`实例传递给需要它的函数,而不是依赖于某些全局可用的单例。闭包是另一种方法,其中您封闭一个值,例如在`(let [x 1] (fn [] x))`中,`fn`是一个封闭`x`的闭包。在`::other-key`组件中,您可以创建一些函数,它们封闭`MyObject`的该实例,而无需将其作为参数传递。
我知道闭包是什么,但是我没有在这里联系起来。所以我想使用`MyObject`对象的方法,它是作为integrant的`init-key`实例化的。对不起如果我谈得太长了。我将尝试阅读更多关于“组件”应该如何工作的内容。非常感谢您的耐心!
...