Мне очень нравится рама, но я понимаю, что у меня проблемы с поиском хорошего шаблона для обработки ответов AJAX.Как следует обрабатывать ответы AJAX об успешности/ошибках в повторной кадре Clojure?
Моя ситуация следующая:
У меня есть «глобальный» обработчик событий, который вызывает некоторые AJAX вызова и отправляет в какой-то другой глобальный обработчик события, в зависимости от того, был ли этот вызов успешным, например:
(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
и прочее, я просто избегаю этого здесь для краткости и потому, что я думаю, что это не имеет никакого значения для моей проблемы).
У меня тоже есть (несколько, различные) компонентов пользовательского интерфейса, которые могут вызвать в :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]))}])))
Таким образом, в этом случае компонент имеет локальное состояние (processing?
), который, как предполагается, будет зависеть от того, вызов AJAX все еще выполняется или нет.
Теперь, что такое правильный шаблон здесь, чтобы иметь button
компонент реагировать на события :store-value-success
и :store-value-error
для того, чтобы сбросить флаг processing?
обратно false
после вызова AJAX закончил?
В настоящее время я работаю над этой проблемой, передавая обратные вызовы, но это кажется действительно уродливым, потому что он загромождает код обработчиков событий тем, что на самом деле не принадлежит.
Лучшее решение, что я думал о том, чтобы иметь button
компонент будучи в состоянии зацепить в :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]))}])))
Однако , это не работает. Кажется, что re-frame не разрешает нескольким обработчикам событий для каждого события. Вместо этого последующий вызов reg-event-db
на один единственный идентификатор события заменит предыдущий обработчик событий.
Итак, как вы, парни, справляетесь с такими ситуациями?
Также взгляните на https://github.com/Day8/re-frame-http-fx –
Спасибо, я знал об этом. Однако я не вижу, как это решает описанную проблему. Я что-то упускаю? – Oliver
Нет, просто хотел привлечь его к вашему вниманию. :) –