clojure - 在 Clojure 重构中应该如何处理 AJAX 成功/错误响应?

标签 clojure re-frame

我喜欢重新构建,但我意识到在寻找处理 AJAX 响应的良好模式时遇到了一些麻烦。

我的情况如下:

我有一个“全局”事件处理程序,它会触发一些 AJAX 调用并分派(dispatch)到其他一些全局事件处理程序,具体取决于该调用是否成功,例如:

(reg-event-db :store-value
  (fn [db [_ value]]
    (do-ajax-store value
                   :on-success #(dispatch [:store-value-success %])
                   :on-error   #(dispatch [:store-value-error %])
    db))

(reg-event-db :store-value-success
  (fn [db [_ result]]
    (assoc db :foobar result)))

(reg-event-db :store-value-error
  (fn [db [_ error]]
    (assoc db :foobar nil
              :last-error error)))

(我知道 reg-event-fx 之类的东西,为了简洁起见,我只是在这里避免使用它,因为我认为它对我的问题没有任何影响)。

我还有(多个不同的)UI 组件可能会触发 :store-value 事件,如下所示:

(defn button []
  (let [processing? (reagent/atom false)]
    (fn button-render []
      [:button {:class (when @processing? "processing")
                :on-click (fn []
                            (reset! processing? true)
                            (dispatch [:store-value 123]))}])))

因此,在这种情况下,组件具有本地状态(处理?),该状态应该取决于 AJAX 调用是否仍在进行中。

现在,让 button 组件对事件 :store-value-success:store-value-error 使用react的正确模式是什么 以便在 AJAX 调用完成后将 processing? 标志重置回 false

目前,我正在通过传递回调来解决这个问题,但这看起来真的很难看,因为它用不真正属于那里的东西混淆了事件处理程序的代码。

我想到的最佳解决方案是让 button 组件能够 Hook :store-value-success: store-value-error 事件并为这些事件安装自己的处理程序,如下所示:

(defn button []
  (let [processing? (reagent/atom false)]
    (reg-event-db :store-value-success
      (fn [db _]
        (reset! processing? false)))
    (reg-event-db :store-value-error
      (fn [db _]
        (reset! processing? false)))
    (fn button-render []
      [:button {:class (when @processing? "processing")
                :on-click (fn []
                            (reset! processing? true)
                            (dispatch [:store-value 123]))}])))

但是,这不起作用。看起来,重新框架不允许每个事件有多个事件处理程序。相反,对单个事件 ID 的后续调用 reg-event-db 将替换先前的事件处理程序。

那么,遇到这样的情况,你们都是怎么处理的呢?

最佳答案

我认为 reg-event-fx ( src ) 可能确实有助于解决您的问题。

您可以添加一个订阅来监视应用程序状态,例如

(rf/reg-sub
  :app-state
  (fn [db]
    (get db :app-state)))

并将其添加到您的按钮,也许带有状态函数,例如

(defn btn-state [state]
  (if (= state :processing)
     "processing"))

然后在 AJAX 处理程序中,您可以添加一个 fx 来更新状态 -

(reg-event-fx              ;; -fx registration, not -db registration
  :ajax-success
  (fn [{:keys [db]} [_ result]]             
     {:db       (assoc db :app-state :default)         
     :dispatch [:store-value-success result]}))

 (reg-event-fx              ;; -fx registration, not -db registration
    :ajax-error
      (fn [{:keys [db]} [_ result]]             
         {:db       (assoc db :app-state :default)         
         :dispatch [:store-value-error result]}))

并更新 AJAX 处理程序

(reg-event-db :store-value
  (fn [db [_ value]]
    (do-ajax-store value
               :on-success #(dispatch [:ajax-success %])
               :on-error   #(dispatch [:ajax-error %])
    db))

这是通过 -fx 处理它的一种方法。我认为您已经开始意识到跟踪应用程序状态的必要性,并且我认为将其添加到订阅中将有助于降低复杂性,此时您的按钮渲染将大大简化。

 (defn button []
      [:button {:class (btn-state @app-state)
                :on-click (dispatch [:store-value 123]))}])))

关于clojure - 在 Clojure 重构中应该如何处理 AJAX 成功/错误响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41569038/

相关文章:

ClojureScript。重新渲染时重置 Reagent 中的原子

Clojure 等价于 Lisp 的 atom 函数

clojure - 通过 Clojure 中的任意函数传输数据

lisp - 复合 boolean 测试的 Clojure(或 Lisp)等价物

clojure - 如何在 Clojure 中重载 "get"

Clojure 解构映射的快捷方式

react-native - 数据源属性不会从试剂传播到 React Native ListView 组件的渲染方法

clojure - 为什么在此 ClojureScript 片段中使用 ^ 字符?

semantic-ui - Clojurescript Semantic UI React Search 自定义渲染器

javascript - Reagent 不会在 let 内部使用 deref-ing 重新渲染组件