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

欢迎!请查看关于页面了解更多关于如何使用本站的详细信息。

+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…>}。根据你如何结构化你的应用,你可以把这个地图存到一个变量或原子中,或者你可以把它作为一个参数传递给你的ring中间件,以便在每次请求中都有一个引用,等等。

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

0 投票
by

您将该代码: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}}}
by
我想在defmethod外面使用它。我想在正常的函数中使用`MyObject`。
by
这样就会不当使用Integrant,几乎将整个系统抛在窗外。您可以给普通函数提供一个额外的参数,这个参数来自某个地方并包含该对象;您可以在`::other-key`组件中将这些函数作为闭包创建;您可以使其成为协议的一部分,并从`::other-key`组件返回实现的对象。所以您的问题的解决方案是有的,创建全局单例不是正确的做法。
by
我不确定我是否理解了有关"带额外参数的普通函数..."的解决方案。你能给我举个例子吗?
每个函数都有一个调用者。您不需要依赖于某个全局可用的单例,可以为每个调用者传递额外的参数,该参数包含`MyObject`的实例给那些需要它的函数。闭包是另一种方法,您可以在闭包中包含一个值,例如在`(let [x 1] (fn [] x))`中,`fn`是一个闭包,它依赖于`x`。在`::other-key`组件中,您可以在不作为参数传递的情况下,创建依赖于该`MyObject`实例的函数。
我知道闭包是什么,但我无法将其联系起来。因此,我想使用作为集成`init-key`的一部分实例化的`MyObject`对象的方法。如果这一点很长,请见谅。我将尝试了解更多关于“组件”如何工作的信息。非常感谢您的耐心!
...