2024 年 Clojure 状态调查! 分享你的想法。

欢迎!请查看 关于 页面,了解更多有关该功能的信息。

+1
Libs

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

我想使用 Integrant 来创建和销毁一个对象。像往常一样,我定义了 defmethods init-keyhalt-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) 时,它会按 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创建的实例。

例如,如果您在Aero中使用Integrant,这可能看起来像这样

;; 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`实例化的。抱歉如果这篇文章太长了。我将尝试阅读更多关于组件应该如何工作的内容。非常感谢您的耐心!
...