Clojure 2024状态调查中分享您的想法!

欢迎!请访问关于页面了解更多此网站的工作方式。

+1

嗨,大家好,我正在尝试使用Integrant库进行状态管理。在管理(启动/停止)服务器时,它的操作非常直观,但我对某个特定用例感到困惑。

我想使用Integrant来实例化并销毁一个对象。像我通常那样,我定义了defmethods init-keyhalt-key! 。问题是我想从init-key中获取已初始化对象的引用。有没有一种符合习惯的方式来做这件事?我应该在我的init-key中将其放在一个原子中使其可用吗?

(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…>}。根据您应用的结构,您可以把这个映射放入一个var或一个原子中,或者将其作为参数传递给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` 实例的闭包函数。
我知道什么是闭包,但在这里我无法串联这些点。因此,我想使用作为 integrant 的 `init-key` 部分实例化的 `MyObject` 对象的 `MyObject` 方法。如果我觉得写得过长,请见谅。我会试着了解更多关于 "组件" 应该如何工作的信息。非常感谢您的耐心!
...