首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从处理程序访问reitit路由信息时避免循环依赖

从处理程序访问reitit路由信息时避免循环依赖
EN

Stack Overflow用户
提问于 2021-08-02 16:50:02
回答 2查看 216关注 0票数 1

假设我设置了某种路由器,把一些路由映射到处理程序,就像这样.

代码语言:javascript
复制
(ns myapp.user.api
  (:require [reitit.core :as r]))

; define handlers here...

(def router
  (r/router
    [["/user" {:get {:name ::user-get-all
                     :handler get-all-users}}]
     ["/user/:id"
      {:post {:name ::user-post
              :handler user-post}}
      {:get {:name ::user-get
             :handler user-get}}]]))

然后那些处理程序调用那些想要访问路由信息的服务..。

代码语言:javascript
复制
(ns myapp.user-service
  (:require [myapp.user.api :as api]))


; how can I get access to the route properties inside here..?
(defn get-all-users [])
  (println (r/route-names api/router)))

当我试图将路由器从api文件导入到服务中时,我会遇到循环依赖的问题,因为api需要处理程序,这需要服务,所以服务就不需要api了。

避免循环依赖的最佳方法是什么?我可以从服务中查找路由器的值和属性吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-08-03 09:09:11

我使用了六种通用方法来避免clojure中的循环依赖。他们都有不同的权衡,有些情况下,一种比另一种更适合。我把它们按顺序排列,从我最喜欢的到最不喜欢的。

下面我给出了一个例子。也许有更多的方法我还没有想到,但希望这能给你一些思考这个问题的方法。

  1. 重构代码以将常见引用的vars移除到新的命名空间中,并要求从两个原始名称空间中都使用该名称空间。通常这是最好也是最简单的方法。但是不能在这里执行,因为根处理程序var是包含来自另一个命名空间的var的文字。
  2. 在运行时将依赖的值传递到函数中,以避免字面上要求命名空间。
代码语言:javascript
复制
(ns circular.a)

(defn make-handler [routes]
  (fn []
    (println routes)))
代码语言:javascript
复制
(ns circular.b
  (:require [circular.a :as a]))

(def routes
  {:handler (a/make-handler routes)})

;; 'run' route to test
((:handler routes))
  1. 使用多个方法来提供分派机制,然后将绑定从另一个命名空间中删除。
代码语言:javascript
复制
(ns circular.a
  (:require [circular.b :as b]))

(defmethod b/handler :my-handler [_]
  (println b/routes))
代码语言:javascript
复制
(ns circular.b)

(defmulti handler identity)

(def routes
  {:handler #(handler :my-handler)})
代码语言:javascript
复制
(ns circular.core
  (:require [circular.b :as b]

            ;; now we bring in our handlers so as to define our method implementations
            [circular.a :as a]))

;; 'run' route to test
((:handler b/routes))
  1. 使用在运行时解析的var文字。
代码语言:javascript
复制
(ns circular.a)

(defn handler []
  (println (var-get #'circular.b/routes)))
代码语言:javascript
复制
(ns circular.b
  (:require [circular.a :as a]))

(def routes
  {:handler a/handler})

;; 'run' route to test
((:handler routes))
  1. 将代码移动到同一个命名空间中。
代码语言:javascript
复制
(ns circular.a)

(declare routes)

(defn handler []
  (println routes))

(def routes
  {:handler handler})

;; 'run' route to test
((:handler routes))
  1. 使用状态。在运行时将其中一个值存储在原子中。
代码语言:javascript
复制
(ns circular.a
  (:require [circular.c :as c]))

(defn handler []
  (println @c/routes))
代码语言:javascript
复制
(ns circular.b
  (:require [circular.a :as a]
            [circular.c :as c]))

(def routes
  {:handler a/handler})

(reset! c/routes routes)

((:handler routes))
代码语言:javascript
复制
(ns circular.c)

(defonce routes (atom nil))
票数 5
EN

Stack Overflow用户

发布于 2021-08-02 20:04:42

你在某个地方犯了一个简单的错误。我的例子:

代码语言:javascript
复制
(ns demo.core
  (:use tupelo.core)
  (:require
    [reitit.core :as r]
    [schema.core :as s]
  ))

(defn get-all-users [& args] (println :get-all-users))
(defn user-post [& args] (println :user-post))
(defn user-get [& args] (println :user-get))

; define handlers here...
(def router
  (r/router
    [
     ["/dummy" :dummy]
     ["/user" {:get {:name ::user-get-all
                     :handler get-all-users}}]
     ["/user/:id"
      {:post {:name ::user-post
              :handler user-post}}
      {:get {:name ::user-get
             :handler user-get}}]
     ]))

并在此使用:

代码语言:javascript
复制
(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test)
  (:require
    [clojure.string :as str]
    [reitit.core :as r]
  ))

(dotest 
  (spyx-pretty (r/router-name router))
  (spyx-pretty (r/route-names router))
  (spyx-pretty (r/routes router))
)

其结果是:

代码语言:javascript
复制
*************** Running tests ***************
:reloading (demo.core tst.demo.core)

Testing _bootstrap

-----------------------------------
   Clojure 1.10.3    Java 15.0.2
-----------------------------------

Testing tst.demo.core
(r/router-name router) =>
:lookup-router

(r/route-names router) =>
[:dummy]

(r/routes router) =>
[["/dummy" {:name :dummy}]
 ["/user"
  {:get
   {:name :demo.core/user-get-all,
    :handler
    #object[demo.core$get_all_users 0x235a3fc "demo.core$get_all_users@235a3fc"]}}]]

Ran 2 tests containing 0 assertions.
0 failures, 0 errors.

基于我的最喜欢的模板项目

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68625303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档