clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
joshkh 2020-10-18T08:45:43.085800Z

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

alpox 2020-10-18T09:10:31.093300Z

@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)

joshkh 2020-10-18T09:22:33.097500Z

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")))))

thheller 2020-10-18T09:33:04.098400Z

@joshkh you cannot block in CLJS/JS. it is a single thread so if you were to block nothing else would happen.

joshkh 2020-10-18T09:51:02.100100Z

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

joshkh 2020-10-18T09:54:07.100800Z

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

thheller 2020-10-18T09:56:15.101300Z

async/await functions also just return a promise. so pretty much the same as go

alpox 2020-10-18T11:37:33.103100Z

@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)

joshkh 2020-10-18T12:26:39.104300Z

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

joshkh 2020-10-18T12:29:45.104800Z

just me being picky

Calum Boal 2020-10-18T13:29:17.107800Z

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?

Calum Boal 2020-10-18T13:31:06.108400Z

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

Calum Boal 2020-10-18T13:31:46.109Z

if i just do (str %1) in the handler i get this

euccastro 2020-10-18T14:01:04.111200Z

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

2020-10-19T09:58:42.115800Z

pretty sure I have seen these working in shadow https://github.com/henryw374/time-literals

2020-10-19T09:59:07.116100Z

I use figwheel mostly. no problems there

Jan K 2020-10-19T10:18:33.116500Z

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

2020-10-19T13:40:59.121600Z

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/

euccastro 2020-10-19T16:45:03.122800Z

thanks! that may be true, but that article only shows that they work for writing/printing, not for reading. Have you tried that?

euccastro 2020-10-19T16:46:18.123Z

and in particular, reading them as data literals from cljs sources or REPLs (i.e., not from strings via edn/read-string)

2020-10-19T16:56:56.123600Z

I know it works reading in repl

euccastro 2020-10-19T17:14:06.123800Z

nice, thanks!

victorb 2020-10-18T14:11:58.111500Z

Are they maybe JS values, not CLJS values?

victorb 2020-10-18T14:12:35.111700Z

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

Jan K 2020-10-18T14:18:01.111900Z

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.

1
Calum Boal 2020-10-18T14:45:22.112200Z

I figured it out, apparently i needed to put :keywords? true in the ajax call. Thanks for getting back to me.

victorb 2020-10-18T14:45:51.112400Z

ah, yeah, otherwise you get string keys 🙂 Happy you got it to work!

Calum Boal 2020-10-18T14:45:56.112600Z

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

Calum Boal 2020-10-18T14:46:26.112800Z

I think it works by default if you're using transit but i was just using json as transit was messing up with timestamps.

victorb 2020-10-18T14:46:46.113Z

yeah, or if your JSON keys have ":" in them, I think