i'm using a library that returns a database connection from a Promise. i'd like to make this library as synchronous as possible so that the db
symbol in the example below can be referenced directly without taking from a channel. in other words, i want to block everything until it is resolved.
(ns db-test
(:require ["local-db-driver" :as client]))
; .connect returns a JS promise: #object[Promise [object Promise]]
; and i want to block until it is resolved...
(def db (.connect client))
; so that 'db can be used elsewhere in the namespace
; without taking from a channel
(.putItem db #{:id 1 :value 3})
i looked into Promise Interop [1] with core async, as well as Promesa [2], but i'm still not getting how i can block given that <!!
isn't available in CLJS
[1] https://clojurescript.org/guides/promise-interop
[2] https://github.com/funcool/promesa@joshkh im coming from the js world and have less experience with cljs.
The only real way to block in js is to park with a loop. And that is usually not recommended.
Better practice is to defer the usage of db
to functions which are only called after db
is resolved and not to use db
on namespace initialization.
Another rather nice practice ive seen from mongoose
is to build an abtraction/proxy around the functions which use db
and queue up all requests/async tasks internally until db
is resolved and only then execute them. This needs all your methods to be asynchronous as well though (returning a promise or similar)
thanks @alpox for your input! even with queueing up requests and async tasks (which sounds great), it's still not clear to me how i can ultimately deliver the resolved results of, say an async db query, in a synchronous manner. it seems that once i'm in a go
block then it's channels all the way to the top. for example
(defn list-users []
; returns a channel
(go
(let [db (<p! (.db client))]
(<p! (.query db "users")))))
@joshkh you cannot block in CLJS/JS. it is a single thread so if you were to block nothing else would happen.
gotcha. so there is no way for me to emulate https://stackoverflow.com/questions/8775262/synchronous-requests-in-node-js (where async functions appear synchronous) without returning a channel
async/await functions also just return a promise. so pretty much the same as go
@joshkh promesa gives you an async/await like interface but you would just get another promise for it as in JS for usual too. There also is no top-level async/await in js (yet)
right, that's what i feel that i'm missing here 🙂. it's not really an issue i suppose, it's just that i'm trying to port a synchronous CLJ library to CLJS and i would love for the syntax to look identical
just me being picky
Hey everyone, just trying to make my first clojurescript app but having issues with ajax calls. I'm using luminus with reagent, i've set up some basic crud endpoints which i'm calling here
(defn debug-handler [response]
(js/console.log (str (map :title response))))
(defn to-atom [atom response]
(reset! atom response))
(defn fetch-todos! [data]
(ajax/GET "/todos"
{:handler #(js/console.log (str (map :title %1)))
:response-format :json
:error-handler (fn [{:keys [status status-text]}]
(js/console.log status status-text))}))
However, i can't get data from the response. As you can see there im trying to console log the values of titles in the map, but i just get (nil nil nil) printed out. If i do (keys %1)
all the keys are printed out fine, and if i do (vals %1)
all the values are printed fine. So why can't i get the values from the map using keys?I did (type (first %1))
to verify that it's actually a map im receiving as well.
if i just do (str %1)
in the handler i get this
Are user-defined tagged literals supported in clojurescript? I found this related issue, which is closed with the comment that "In a post conditional reading world we have a real solution to this problem." What is that solution? https://clojure.atlassian.net/browse/CLJS-335
pretty sure I have seen these working in shadow https://github.com/henryw374/time-literals
I use figwheel mostly. no problems there
Maybe they work better as libraries, but in my project code I've had a lot of trouble with them... Here the author of shadow says it's not supported: https://github.com/thheller/shadow-cljs/issues/272
yeah maybe - although that would be weird - it's all just stuff on the classpath - anyway I checked and the time-literals do work in shadow as shown here http://widdindustries.com/tick-with-shadow-just-works/
thanks! that may be true, but that article only shows that they work for writing/printing, not for reading. Have you tried that?
and in particular, reading them as data literals from cljs sources or REPLs (i.e., not from strings via edn/read-string)
I know it works reading in repl
nice, thanks!
Are they maybe JS values, not CLJS values?
can you share the full output of js/console.log
for the handler without manipulating it?
They are supported, you can have data_readers.cljc
. But beware that shadow-cljs doesn't support it and figwheel-main and other tools may have issues with it too.
I figured it out, apparently i needed to put :keywords? true
in the ajax call. Thanks for getting back to me.
ah, yeah, otherwise you get string keys 🙂 Happy you got it to work!
was driving me crazy for a while as all the examples i found on line didn't have that haha
I think it works by default if you're using transit but i was just using json as transit was messing up with timestamps.
yeah, or if your JSON keys have ":" in them, I think