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

欢迎!请查看关于页面了解更多该服务的信息。

+1

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

我想使用 Integrant 来实例化和销毁一个对象。像我平常一样,我定义了 defmethods init-keyhalt-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…>}。根据你的应用程序的结构,你可以把这个映射放入一个 var 或一个 atom 中,或者你可以将它作为参数传递给你的 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`实例化的。如果写得有点长,请见谅。我将尝试了解更多关于“组件”应该如何工作。非常感谢您的耐心!
...