Fork me on GitHub
Kurt Harriger03:01:57

question: when using shadow-cljs repl and I often want to print result of an async function, but since js is non-blocking I need to do something like (go (pprint (<! (get-some-data))). This will print the result to the js/console but in the repl I only see #object[cljs.core.async.impl.channels.ManyToManyChannel] and thus I need to tab back and forth from browser… In js console I can use await when calling async functions but I think thats a browser console specific thing. Any chance there is a way to have to repl subscribe to a promise and print the result when its available


not that simple unfortunately. I thought about adding a REPL primitive to wait for an async result but since you can't block that might "deadlock" the entire REPL. I'd recommend tap> and Inspect instead if pprint so that doesn't have that issue?

Kurt Harriger16:01:43

Thanks. I’m not as familiar with tap> from docs it seems like add-tap allows you to register multiple callbacks such as println or some other behavior, eg inspect? what do you mean by inspect. Do you mean (.dir js/console object) ? I do get messages in the js console just not the repl, so trying to see if there is some method to send a message to the repl when its completed. I don’t necessarily think the repl needs to block, I think it would be fine if you see a prompt and then when data is ready its pushed to the repl… but i’m not sure if there is anyway for the app to push anything to the repl after the command is completed. I assume it waits until the command completes and then stops listening to the out stream so probably not possible but thought it worth asking to see if its feasible


you just (tap> value) and it'll show up in the inspect ui, usually available at http://localhost:9630/inspect


the issue is much more in nrepl than it is in shadow-cljs. nrepl isn't expected to receive two return values for one eval so it'll either just discard the second or freak out. depends on your editor


Is there any way my code can know whether it’s running as a release build or as a regular dev build (through watch)?


Currently, I do it this way, but it feels like a hack:

(def main-js
  "When making a release, the filename will be appended with a hash;
  that is not the case when running the regular shadow-cljs watch process.

  Relies on the :module-hash-names being set to true in shadow-cljs.edn."
  (if-let [url (io/resource "public/js/compiled/manifest.edn")]
    (-> url slurp edn/read-string first :output-name)

(def development?
  "Source of truth for whether this is a development build or not. "
  (= main-js "main.js"))


Can you check goog/DEBUG?


You are in clojure, not clojurescript. That won't work. Nevermind me

Kurt Harriger16:01:05

I assume your build process could define some environment as part of the different build configurations and you could check that?


> my code can know whether it’s running as a release build or as a regular dev build


define "my code"? the snippet you posted is clojure? do you want to know in CLJS or CLJ?


for CLJS the answer would be closure defines and setting a different value for :release. see


Right, the reason I do it in Clojure is because I’m generating the html page dynamically using Clojure and then I pass that on to CLJS. I need to know in both 🙂


on the CLJ side just always use the manifest. dev builds also generate it. dunno why you'd need to know if its a dev build though. for CLJS see :closure-defines above


On the CLJ side I do it to disable CORS/authz and on the CLJS side I mostly use it as way to indicate that those things are disabled.


IMHO that should be a setting on the CLJ side and not be derived from what CLJS you are using


It is a setting (I mean, I can always just hardcode the boolean to some value), but it’s nice that it’s working automatically in 99% of cases ;-)