This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # aleph (1)
- # architecture (4)
- # beginners (39)
- # boot (12)
- # cider (25)
- # cljs-dev (3)
- # cljsrn (5)
- # clojure (175)
- # clojure-dusseldorf (1)
- # clojure-italy (13)
- # clojure-nl (4)
- # clojure-russia (1)
- # clojure-spec (52)
- # clojure-uk (110)
- # clojurescript (35)
- # data-science (2)
- # datomic (61)
- # editors (8)
- # emacs (2)
- # fulcro (7)
- # graphql (15)
- # hoplon (1)
- # hyperfiddle (3)
- # jobs (4)
- # jobs-discuss (12)
- # juxt (2)
- # lein-figwheel (6)
- # leiningen (35)
- # off-topic (4)
- # onyx (5)
- # parinfer (1)
- # pedestal (63)
- # re-frame (38)
- # reitit (7)
- # ring-swagger (7)
- # rum (2)
- # shadow-cljs (27)
- # tools-deps (10)
- # uncomplicate (16)
Something is puzzling me. I have a subscription that returns all the forms in app-db. I pass that as an input signal to a subscription that pulls out a specific form from the list, e.g.
:contact-form. I pass that as an input signal to a subscription that gets a specific field from the form, say
:first-name. And lastly, I pass that as an input signal to a subscription that returns an error message if the field is blank. That’s a bit oversimplified, but you get the idea.
If I add debugging statements to print out each subscription as it runs, I see this pattern consistently:
Getting error message from field Getting form from forms Getting field from forms
If I make changes to the field, the error message subscription receives the value as it was prior to my changes to the field. The other subscriptions receive the up-to-date value.
Sounds like a “glitch”. btw, I enjoyed hearing that intricate dataflow described as “oversimplified”. 🙂
More seriously, I am surprised since I have seen the signal graph described as de-duplicated (not sure on the term) which maes me think this sort of thing would be well worked out. Lemme consult The Google.
fwiw, I asked over on #reagent if propagation was glitch-free and never heard back.
One ref on glitches: https://en.wikipedia.org/wiki/Reactive_programming#Glitches
If it were a glitch, btw, you would see “getting error message” twice, once with an obsolete value but then again when the data flow propagation “catches up”.
If you do a cold restart do you see that sequence? https://github.com/Day8/re-frame/blob/master/docs/FAQs/Why-Clear-Sub-Cache.md
Yes, this is reproducible across a co-worker checking in his code and me checking it out and running it on my machine, having never run it before, and with me selecting “Empty Cache and Hard Reload” in Chrome while reloading
@mikethompson I’m looking at 10x, but the Subs tab is a bit odd, it’s showing a different order of execution than my
println’s are showing
This is using older code that creates subscriptions and passes them to the child; I’m about to do a refactor to standardize on just passing the subscription vectors and letting each component manage its own subs
I am trying to remember some hack required to get async console output manageable, but not even sure it was CLJS.
You said “co-worker” so I am guessing this is not O/S. I have been thinking about blogging on reactive systems and this is the kind of thing I would be tearing into. I know it is hours of work, but can this be distilled into a shareable 30-40 lines?
Also, I joked about it being oversimplified, but that is probably where the problem lies. If what you meant was that other subscriptions were involved, then there could be multiple paths leading from the original change to the “error message” computation. Glitches arise when a signal follows a shorter path bypassing other paths on which “error message” depends.
Well, there’s not really multiple paths involved, it’s just straight A -> B -> C -> D.
If I didn’t want the subscription “magic” to happen, it would just be
(get-in db [:forms :contact-form :first-name :value]) (plus the code to check the value for errors).
btw, what order did the Subs tab show? If it was what you suspected it should be, your logging (or 10x’s) is suspect.
I think we are on to something. 🙂 Lemme refresh my memory on the unreliable console issue… mind you, you are seeing old data in the error message sub, but then that could be from something else….I love this game!
Not sure this applies to CLJS: http://yellerapp.com/posts/2014-12-11-14-race-condition-in-clojure-println.html
Somewhere else I saw a suggestion to call
(flush) after every println. Again, clojure was the context.
I know JS is single-threaded, I just like touching all the bases. But I think because you are indeed seeing old data we can concentrate on that and trust the console.
`Reagent re-runs reactions (re-computations) via requestAnimationFrame. So a re-computation happens about 16ms after an input Signals change is detected, or after the current thread of processing finishes, whichever is the greater. So if you are in a bREPL and you run the lines of code above one after the other too quickly, you might not see the re-computation done immediately after n gets reset!, because the next animationFrame hasn't run (yet). But you could add a (reagent.core/flush) after the reset! to force re-computation to happen straight away.
Yeah, but I don’t think that applies in this case does it? Since the
prn is inside the re-computation, we know that we’re already past the point where any delay in starting the recomputation might occur
Your problematic recomputation is running before the one (field) that would have provided the current value. I note, btw, that form does run before field, so that’s OK.
Well, I did find a misspelled key in my data, and I fixed that, and now I’m not seeing the out-of-order subscription values :table-flip: Maybe I’ll just take the rest of the day off now.
Not sure if there might be more interest, or constructive redirection!, in this observer handler type I'm partway through creating. It is basically doing what reg-sub-raw does, but going into a special seq so that a component can opt-in to subscribe to all observers to get them to be triggered. I've included a basic motivating example to demonstrate the type of business logic we have enjoyed moving to these observers and cleaning up our code base. Would appreciate any feedback if there is a better pattern out there or a more idiomatic way to do this in re-frame. https://github.com/lumanu/re-frame-observers