Как сделать так, чтобы обработчики запускались последовательно в повторном кадре?

Начиная с этих двух обработчиков, которые заботятся о получении информации о текущем пользователе:

(re-frame/register-handler
  :got-user
  (fn [db [_ user]]
    (assoc db :user user)))

(re-frame/register-handler
  :get-user
  (fn [db [_]]
    (ajax/GET "/user" 
       {:handler #(re-frame/dispatch [:got-user %1])})
    db))

на одной странице я хочу отобразить список друзей, но проблема в том, что это зависит от пользователя, которого выбирают в первую очередь:

(re-frame/register-handler
  :get-friends
  (fn [db [_]]
    (when (nil? (:user db))
      (re-frame/dispatch [:get-user]))
    ; Here's the problem, as I need to way for get-users and got-users to run.
    (ajax/GET (str "/users/" (get-in db [:user :id])) 
       {:handler #(re-frame/dispatch [:got-friends %1])})
    db))

Как мне структурировать этот код?

2 ответа

Во-первых, документация специально предупреждает против создания обработчиков с побочными эффектами (т. Е. Отправки событий от обработчиков событий). Во-вторых, не пытайтесь повторно использовать обработчики событий, но реорганизуйте повторно используемые части в вспомогательные функции. Используя re-frame-http-fx, я бы написал что-то вроде этого:

(reg-event-fx
  :get-friends
  [trim-v]
  (fn
    [{db :db} [_]]
    {:http-xhrio  (if (:user db)
                  {:method          :get
                  :uri             (str "/users/" (get-in db [:user :id])) 
                  :on-success      [:got-friends]
                  :on-failure      [:get-friends-load-failed]}

                  {:method          :get
                  :uri             "/user" 
                  :on-success      [:get-friends-for-user]
                  :on-failure      [:get-friends-user-load-failed]})
     :db         db}
    ))

Затем get-friends-for-user сначала сохранит полученного пользователя и начнет извлекать друзей.

Вдохновившись статьей о решении проблемы с загрузкой процессора, я заставил get-friends звонить сам, пока пользователь равен нулю, но чтобы избежать отправки большого количества запросов на сервер, он также добавляет флаг о запрашиваемом пользователе:

(re-frame/register-handler
  :get-friends
  (fn [db [_ user-requested]]
    (if-let [user (:user db)]
      (ajax/GET (str "/users/" (get-in db [:user :id]))
                {:handler #(re-frame/dispatch [:got-friends %1])})
      (do
        (when (not user-requested)
          (re-frame/dispatch [:get-user]))
        (re-frame/dispatch [:get-friends true])))
    db))

Это работает, но на локальной машине ему удается вызывать себя 9 раз или около того, пока пользователь-пользователь не установит пользователя. Не уверен, если это будет проблемой или нет, и я открыт для других решений, если они существуют.

Другие вопросы по тегам