Fork me on GitHub

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] [2]


@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
    (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 (where async functions appear synchronous) without returning a channel


no worries 🙂 core.async it is. thanks @alpox and @thheller


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

Calum Boal13:10:17

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?


Are they maybe JS values, not CLJS values?


can you share the full output of js/console.log for the handler without manipulating it?

Calum Boal14:10:22

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!

Calum Boal14:10:56

was driving me crazy for a while as all the examples i found on line didn't have that haha

Calum Boal14:10:26

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

Calum Boal13:10:06

I did (type (first %1)) to verify that it's actually a map im receiving as well.

Calum Boal13:10:46

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?

Jan K14:10:01

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.

thanks2 3

pretty sure I have seen these working in shadow


I use figwheel mostly. no problems there

Jan K10:10:33

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:


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


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!