This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # announcements (2)
- # beginners (97)
- # boot (3)
- # cider (23)
- # clara (9)
- # cljs-dev (40)
- # cljsrn (6)
- # clojure (107)
- # clojure-finland (2)
- # clojure-india (3)
- # clojure-italy (15)
- # clojure-nl (2)
- # clojure-spec (107)
- # clojure-uk (91)
- # clojurescript (28)
- # cursive (10)
- # data-science (4)
- # datomic (26)
- # duct (1)
- # emacs (6)
- # events (9)
- # figwheel-main (4)
- # fulcro (4)
- # graphql (2)
- # jobs (3)
- # jobs-discuss (12)
- # juxt (7)
- # kaocha (6)
- # off-topic (8)
- # onyx (2)
- # parinfer (13)
- # pedestal (32)
- # portkey (1)
- # re-frame (58)
- # reagent (17)
- # reitit (21)
- # ring-swagger (3)
- # shadow-cljs (35)
- # spacemacs (1)
- # tools-deps (33)
- # yada (13)
What is your favorite way of handling Promise-like situations in ClojureScript / re-frame? I.e. chaining events and handlers like 1. set saving state, 2. save to server call, 3. when success reload from server. Do you use callback(-hell), re-chain, re-frame-async-flow-fx or aramis or what?
@macroz for pure promise composition we use funcool/cats
mlet http://funcool.github.io/cats/latest/#mlet with funcool/promesa promise monad https://github.com/funcool/cats/blob/master/src/cats/labs/promise.cljc
alet for concurrent request flow http://funcool.github.io/cats/latest/#alet
it doesn't - it lets you compose promise operations, then you can spit out an event from the result. if you need the intermediate states in the app-db then one of the other approaches would be more appropriate
generally I think I'm looking for a simple sequential chaining of handlers and the solutions that I found above were either not used much or more complex than I think they should be
composing promises is definitely an answer but I don't see how that works out with re-frame well
it works out fine - promises are a nice abstraction and compose very well - you get a value or an error-state at the end which is straightforward to stick in an event
we have some stuff which holds intermediate states in the app-db, which is currently a mess and will soon be re-frame-async-flow-fx, but that will only be in a couple of places in our 30kloc app
For relatively simple cases I pass “dispatch these if success” -vector to data-fetching events.
Yep. For more complex chaining I’d also consider doing it on server-side if it’s not something purely UI-related.
ha, we use exactly the same promise-chaining model on the server-side - the code would be identical
the exact situation if I have in mind is a chain of saving current form data, uploading attachment, then reloading data
it doesn't make sense to add to API a separate endpoint for save form data and attachment unless you like building backends for frontends much
saving form data and uploading attachment are their own functions as well, only when the form has yet never been saved they need to be chained like this
Do you need to deal with error handling? Should it rollback if any of the calls fail?
for that exact case we don't save the form-data - we upload the attachment on the side, which returns an uploaded file descriptor, which gets used for a thumbnail presentation and as a path for a field in the form, whenever the form gets submitted
so you basically have free floating attachments that you garbage collect somehow separately?
this feature was first implemented so that the attachment must have the form and "application id"
free floating attachments that i will garbage-collect at some point in the future but not until storage becomes more than an insignificant cost 😬
Just started to wonder based on the convo. On a quick look js/FormData seems to support it https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
yes it is! but it is a solution to this specific problem only and not to the genreal chaining needs
idempotent backends that coordinate multiple REST backends by rolling forward are cool but not the original question
Back to on-topic: I think stateful async chaining is quite complex by nature and that’s why general solutions are also complex. Using promises and firing event at the end sounds tempting.. But my gut tells me to avoid that for some reason.
So far my ‘avoidance-strategy’ has worked out well. 😄 Sooner or later I’ll hit the wall though.
I started with
async-flow-fx and then ended up hitting a wall, and now have specific state machines (a map with current-state -> event -> next-state) for every individual flow. On one level it's a right pain, but on another level it's quite clear
Not tried the
alet solution - although I'd be interested to try, I'm just avoiding a big refactor at this stage
@danieleneal nice, so basically every handler calls to a state machine function to select the next dispatch
yeah something like that, based off of http://blog.cognitect.com/blog/2017/8/14/restate-your-ui-creating-a-user-interface-with-re-frame-and-state-machines
https://github.com/tomasd/statecharts i haven't used this in any level of anger yet, but it's a SC implementation targetted to re-frame