将状态作为参数传递给环处理程序?

4ZM*_*4ZM 13 dependency-injection clojure compojure ring

如何最方便地将状态注入环处理程序(不使用全局变量)?

这是一个例子:

(defroutes main-routes
  (GET "/api/fu" [] (rest-of-the-app the-state)))

(def app
  (-> (handler/api main-routes)))
Run Code Online (Sandbox Code Playgroud)

我想the-state进入compojure处理程序main-routes.状态可能类似于使用以下内容创建的地图:

(defn create-app-state []
  {:db (connect-to-db)
   :log (create-log)})
Run Code Online (Sandbox Code Playgroud)

在非环形应用程序中,我将在main函数中创建状态,并开始将其作为函数参数注入到应用程序的不同组件中.

:init不使用全局变量的情况下,可以使用ring 函数完成类似的操作吗?

Ale*_*lex 21

我已经看到过这种做法有两种方式.第一种是使用中间件将状态注入请求映射中的新键.例如:

(defroutes main-routes
  (GET "/api/fu" [:as request]
    (rest-of-the-app (:app-state request))))

(defn app-middleware [f state]
  (fn [request]
    (f (assoc request :app-state state))))

(def app
  (-> main-routes
      (app-middleware (create-app-state))
      handler/api))
Run Code Online (Sandbox Code Playgroud)

另一种方法是替换调用defroutes,在幕后将创建一个处理程序并将其分配给var,其中一个函数将接受某个状态,然后创建路由,将状态作为参数注入到路径中的函数调用定义:

(defn app-routes [the-state]
  (compojure.core/routes
    (GET "/api/fu" [] (rest-of-the-app the-state))))

(def app
  (-> (create-app-state)
      app-routes
      api/handler))
Run Code Online (Sandbox Code Playgroud)

如果有选择,我可能会采用第二种方法.