Fork me on GitHub
#re-frame
<
2020-03-31
>
zalky16:03:08

Hi all, I'm wondering if the re-frame implementation provides a guarantee that two events dispatched via re-frame.core/dispatch are scheduled and processed in the same order that they are dispatched. The router documentation says it uses a FIFO queue. Assuming we can treat these two events independent of all other events, is this a hard guarantee they are handled in the same order? (Clearly a more explicit guarantee would be to re-dispatch sequential events, with possibly added latency).

p-himik16:03:11

I would think so. The implementation works that way.

lilactown16:03:37

barring failures (e.g. an event throws an error), it is the case that events are run in order

lilactown16:03:19

there is no transactional guarantees across multiple events

p-himik16:03:51

Or even one event, because it may use side-effecting effects.

lilactown16:03:13

yeah that’s true. any effects returned by an event are run in random order and may fail

joelsanchez17:03:20

they are run in order until you get to cljs.core/PersistentHashMap at 8+ elements, at which point you might want to pass a sequence of key-val tuples to keep order

joelsanchez17:03:28

feel free to test it

lilactown17:03:08

yeah, that’s an impl detail of persistent hash maps. on the order of guarantees, I would mark that close to nil.

lilactown17:03:50

it’s better to consider a hash map as unordered IMO

p-himik17:03:52

Same with providing key-val tuples. The fact that it works is a happenstance. The documentation says that you have to return a map.

joelsanchez17:03:27

most of the time you don't care about the order, but if you do, you have the option to pass tuples (no matter the size of your map). I think that's useful but it's ok to disagree

joelsanchez17:03:42

sometimes, the code is better than the documentation at explaining behavior.

p-himik17:03:38

If I really had to rely on the order of effects, I would just chain regular events, that each emits the corresponding effect. Follows documentation and you won't have to check the internals of re-frame on each update.

lilactown17:03:15

I’d probably write the effects in a promise chain and have one event/effect that runs it 😛

lilactown17:03:36

IME chaining events and effects is a terrible DX

✔️ 4
p-himik17:03:10

Agglutinating multiple effect handlers into a single one is cheating. :P > chaining events and effects is a terrible DX The question was about emitting the effects in the order, not about making sure that they're handled in order. So it would be like :dispatch-n [...] and not like evt1 -> fx1 -> evt2 ->fx2 ->....

lilactown17:03:36

indeed, we’re off on a tangent now

👍 4
aarkerio17:03:18

hi! quick question:

aarkerio17:03:35

can I add a lazySeq to the db, like: (assoc db :subjects (map #(whatever %) rows))

aarkerio17:03:33

I tried but my "for" loop in the view is never triggered

aarkerio17:03:56

(assoc db :subjects (into {} (map #(whatever %) rows))) works though

p-himik17:03:08

I am pretty sure I use for on map's. How do you use for in your view?

aarkerio17:03:02

(defn display-questions-list  [uurlid question-count]
  (let [questions (rf/subscribe [:questions])]
    (fn [uurlid question-count]
      [:div
       (doall (for [{:keys [idx question]} (zlib/indexado @questions)]
                ^{:key (hash question)}
                [question-item (assoc question :counter idx :uurlid uurlid :qcount question-count)]))]
      )))

aarkerio17:03:07

I use the map function in the "re-frame/reg-event-db" event

aarkerio17:03:44

if I use (into {} themapstuff), all works fine

aarkerio17:03:16

but I don't know if I can pass a lazySeq to the re-frame DB

p-himik18:03:07

I have no idea what indexado is and what the rest of your app looks like, but as I mentioned, it just works for me:

(ns reagent-playground.core
  (:require [re-frame.core :as rf]
            [reagent.dom :as dom]))

(rf/reg-event-db :init
  (fn [_ _]
    {:data []}))

(rf/reg-event-db :update
  (fn [db _]
    (assoc db :data (map rand (range 10)))))

(rf/reg-sub :data
  (fn [db _]
    (:data db)))


(defn app []
  (let [on-click #(rf/dispatch [:update])
        data (rf/subscribe [:data])]
    (fn []
      [:div
       [:button {:on-click on-click}
        "Update"]
       [:div
        "Data"
        (for [v @data]
          ^{:key v}
          [:span [:br] "Item: " v])]])))

aarkerio18:03:39

hmm, I see, thanks a lot p-himik, one question: should I prefer "doseq" instead of "for"?

p-himik18:03:59

Read the doc for doseq: "Returns nil". You cannot use it. for is just fine.