如何从重新构建处理中排除非重新构建原子,例如使用 o'doyle 规则引擎?

问题描述

Clojure:1.10.0
clojurescript:“1.10.764
shadow-cljs "2.11.7"
重新构建“1.2.0”

我正在使用 re-frame 创建一个 SPA,并且一切正常。但是,我最近观看了 video on o'Doyle rules engine 并且我认为在我的重新构建项目中尝试对此进行试验可能会很有趣。它在自己的原子中创建了一个单独的“事实表”:

(ns cube-test.twizzlers.rules
 (:require
  [re-frame.core :as re-frame]
  [odoyle.rules :as o]))

(def rules
  (o/ruleset
    {::print-time
     [:what
      [::time ::total tt]
      :then
      (println "upate time rule:" tt)]}))

;; create session and add rule
(def ^:dynamic *session
  (atom (reduce o/add-rule (o/->session) rules)))

(defn update-time []
  (swap! *session
         (fn [session]
           (-> session
               (o/insert ::time ::total 100)
               o/fire-rules))))

然后我创建了一个按钮来激活更新:

[:button.user-action {:on-click #(re-frame/dispatch [::twiz.events/update-time])} "update time rule"]

规则触发并且一切正常,但是我在控制台上看到一堆重新构建警告,表明重新构建正在尝试将 odoyle 原子作为它自己的一个来挂钩和管理:

"twizzler.events.update-time: entered" cljs.core.js:168:20
upate time rule: 100 cljs.core.js:168:20
re-frame: no handler registered for effect: 
Object { ns: null,name: "alpha-node",fqn: "alpha-node",_hash: 1411603897,"cljs$lang$protocol_mask$partition0$": 2153775105,"cljs$lang$protocol_mask$partition1$": 4096 }
 . Ignoring. cljs.core.js:13285:10
re-frame: no handler registered for effect: 
Object { ns: null,name: "beta-nodes",fqn: "beta-nodes",_hash: -674152665,name: "last-id",fqn: "last-id",_hash: -1231616450,name: "rule-name->node-id",fqn: "rule-name->node-id",_hash: -494456865,name: "node-id->rule-name",fqn: "node-id->rule-name",_hash: 1615893599,name: "id-attr-nodes",fqn: "id-attr-nodes",_hash: -1814751183,name: "then-queue",fqn: "then-queue",_hash: 899186975,name: "then-finally-queue",fqn: "then-finally-queue",_hash: 2088468149,"cljs$lang$protocol_mask$partition1$": 4096 }
 . Ignoring. cljs.core.js:13285:10

“then-finally-queue”和“alpha-node”等。 al 大概是它的原子上的 o'doyle 生命周期事件,看起来 re-frame 正在尝试为它们找到处理程序。

这个问题实际上并不是关于使 odoyle 规则引擎和重新框架一起工作,尽管如果有人对这种情况的合理性有意见,我会很想听听他们的意见(是的,框架之间存在重叠,但我认为 odoyle“事实表”只是一种替代视图,我将通过重新框架订阅进行管理)。

无论如何,为了更清楚地说明这个问题不仅仅是关于 odoyle 或 odoyle 设计的影响,我创建了一个这样的通用原子:

(def ^:dynamic *a* (atom 10))

(defn update-atom []
  (swap! *a* inc))

当我驾驶它时,它会生成

"twizzler.events.update-dmy-atom: entered" cljs.core.js:168:20
Uncaught Error: No protocol method IMap.-dissoc defined for type number: 12
    cljs$core$missing_protocol https://localhost:8281/js/compiled/cljs-runtime/cljs.core.js:312
    cljs$core$IMap$_dissoc$dyn_41386 https://localhost:8281/js/compiled/cljs-runtime/cljs.core.js:2213
    cljs$core$_dissoc https://localhost:8281/js/compiled/cljs-runtime/cljs.core.js:2224
    cljs$core$IFn$_invoke$arity$2 https://localhost:8281/js/compiled/cljs-runtime/cljs.core.js:6832
    re_frame$fx$do_fx_after https://localhost:8281/js/compiled/cljs-runtime/re_frame.fx.js:40
    re_frame$interceptor$invoke_interceptor_fn https://localhost:8281/js/compiled/cljs-runtime/re_frame.interceptor.js:216
    re_frame$interceptor$invoke_interceptors https://localhost:8281/js/compiled/cljs-runtime/re_frame.interceptor.js:255
    re_frame$interceptor$execute https://localhost:8281/js/compiled/cljs-runtime/re_frame.interceptor.js:365
    re_frame$events$handle https://localhost:8281/js/compiled/cljs-runtime/re_frame.events.js:85
    re_frame$router$IEventQueue$_process_1st_event_in_queue$arity$1 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:580
    re_frame$router$IEventQueue$_run_queue$arity$1 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:325
    vec__42331 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:417
    re_frame$router$IEventQueue$_fsm_trigger$arity$3 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:459
    G__42328 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:370
    NextJS 3
    day8$re_frame_10x$inlined_deps$re_frame$v0v12v0$re_frame$router$IEventQueue$_run_next_tick$arity$1 https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:372
    vec__42751 https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:478
    day8$re_frame_10x$inlined_deps$re_frame$v0v12v0$re_frame$router$IEventQueue$_fsm_trigger$arity$3 https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:549
    day8$re_frame_10x$inlined_deps$re_frame$v0v12v0$re_frame$router$IEventQueue$push$arity$2 https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:363
    day8$re_frame_10x$inlined_deps$re_frame$v0v12v0$re_frame$router$dispatch https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:699
    day8$re_frame_10x$db$init_db https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.db.js:24
    day8$re_frame_10x$init_db_BANG_ https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.js:352
    <anonymous> https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.preload.js:3
    globalEval https://localhost:8281/js/compiled/app.js:597
    evalLoad https://localhost:8281/js/compiled/app.js:1690
    <anonymous> https://localhost:8281/js/compiled/app.js:2162
app.js line 597 > eval:312:9

IOTW,re-frame 也在尝试“管理”这个原子。

它看起来像重新框架钩子所有原子处理功能而不仅仅是它自己的应用程序数据库随机

有没有办法标记一个原子以将其从重新构建的钩子中排除?或者我会被迫创建一个非重新构建的项目来试验 odoyle?注意:odoyle 有一个 adapter for Rum,因此它可以与其他响应式框架一起使用。

解决方法

关于多余的消息:

这是来自原始海报的“答案”。由于我没有收到任何回复,我将解释我的发现以及我如何处理这种情况。除了我所知道的框架的基本用户之外,我不声称拥有任何重新框架的专业知识。

查看 re-frame 的源代码(它非常小,顺便说一句也不是很复杂),fx.cljs 似乎是我看到的所有消息的来源。我可以看到实际上它有很多拦截器:

(def do-fx
  (->interceptor
    :id :do-fx
    :after (fn do-fx-after

仔细考虑之后,挂钩和拦截与代码相关而不是与原子相关是有道理的,即您通常会加载一份代码副本来处理 n 个原子。

我对重新框架挂钩非重新框架原子的主要关注有两个方面:性能和干扰。就性能而言,这只是对处理程序进行简单检查的重新框架,没有找到它,并打印警告消息。由于状态更改是在应用程序级别而不是在动画刻度上(我的项目是 Babylon.js 3d 应用程序),所以这不是一个大问题。事实上,添加一个查找表来监视或不监视哪些原子,虽然也不会对性能造成很大的影响,但如果有的话,会进一步降低性能。所以有这些消息没什么大不了的。

我也意识到重新构架根本不应该干扰非重新构架原子。事实上,这些消息表明重新构建无法拦截原生原子。所以再次没有什么可担心的。

所以我能够说服自己,这些消息真的没什么好担心的。然而,有很多多余的冗长消息堵塞我的控制台的幽灵很烦人。

为了处理删除所有消息,我调用了重新构建的 set-loggers! 调用,在那里我使用了正则表达式来过滤多余的消息,例如:

(defn rf-odoyle-warn-override-logger [& args]
  (let [text (apply str args)]
    ; (prn "utils.rf-odoyle-warn-override-logger: text=" text)
    (if (re-matches #".*no handler registered for effect:.*Ignoring.*" text)
      (js/console.log "probable rf-odoyle interceptor no handler msg warning detected")
      (js/console.warn text))))

在我的启动中这样调用:

(re-frame.core/set-loggers!  {:warn utils/rf-odoyle-warn-override-logger})

现在,我只在控制台中收到一条简单的“折叠”消息:

probable rf-odoyle interceptor no handler msg warning detected

关于将 re-frame 和 o'doyle 一起使用:

相对于在重新框架中使用 o'doyle 规则的可行性,我看到了对我的巨大希望,因为我的主要“视图”是一个 babylon.js 场景而不是 DOM。因此我需要在 DOM 之外做很多游戏级别的逻辑,我认为 O-doyle 将补充重新框架。如果您的应用程序是一个基本的 Web 应用程序,其中 DOM 是您的主要视图,那么我认为尝试在重新框架状态(例如在 app.db 中)之上维护 odoyle 状态可能会有些多余。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...