Fork me on GitHub

Hi all, i'm working with a Javascript object that seems to be recursive. If I println it, I get a too much recursion error. When I use js/console.log it gets printed, and there's one key that keeps nesting itself repeatedly. It seems to go infinitely. However my problem is that I want to access a specific portion of this data in the form of..

(-someChildren (-key1 obj))
This will give me a collection of objects, which also recur endlessly! But each one of these children has a property that I want. Basically I want to do this..
(map -someProp (-someChildren (-key1 obj)))
Of course this doesn't work, since it's a Javascript array. And I can't use js->clj or array-seq because of the infinite recursion. What's the best way to tackle this problem? One solution I could think of is using Clojure's loop + .pop until the array is empty, but maybe there's a cleaner way?


if it’s a JS array you can just call JS , can’t you?

(.map (-someChildren (-key1 obj))
      #(-someProp %))


Ah wow, I feel pretty silly haha. Forgot JS has a map method. I think that would work, thanks 🙂


glad I could help 😉 cheers


JS interop is really quite nice in ClJS, but it’s easy to forget about when you write Clojure all the time 😉


Well I'm honestly not an expert in Javascript anyway 😄


Hello everybody, I need some help in end to end testing in clojurescript using shadow-cljs. I saw this for doo is it possible to do something similar for shadow-cljs? I would like run the cljs tests from the test environment of the clojure backend, is that possible or should I migrate to doo?


is there an example or walktrhough somewhere of starting a cljs repl from a clojure repl (not from the command line)?


But it seems like this might just start a server?

Alex Turok13:03:49

I haven’t done any cljs for long, but used to do things as outlined in weasel’s readme. Worked for me - you may try it:


Thanks, but I'm specifically trying to get it to work with no external deps besides cljs. Which I know is possible somehow 🙂 It works if I use clj -m cljs.main from the command line. Just trying to cheat on reverse engineering that


Hi all. Having headaches with cljs-http. I'm playing with ring-compojure and got a server running on localhost:3000. I can make requests to this server via postman / direct in the browser and getting valid json responses. If I try the same request with cljs-http, I'm getting an empty response: '{:status 0, :success false, :body "", :headers {}, :trace-redirects ["http://localhost:3000/..." "http://localhost:3000/...."], :error-code :http-error, :error-text " [0]"} ' what could I be missing. I've looked around to no avail. This "(go (let [response (<! (http/get "" {:with-credentials? false }))] (prn response)))" however works. Only when I use my endpoint do I get this funny empty error.


Turned out to be a CORS issue. Adding cors middleware on the ring server fixed the problem.


how do I convert an asyncIterable in a core.async channel? or implement for await... of ?


As far as I know there's no libraries that do this for you, but based on the it should be simple to make a function that makes such a channel.


My own try at this based on the current spec. Definitely not tested but this should do what you need with some minimal debugging. It takes the same arguments as and operates in a similar fashion. I didn't detail handling errors, so figure out what's appropriate for your use case.


I didn't succeed. I think I didn't fully grasp my problem. I have this socketcluster app which I want to use in clojurescript. I have the working server.js code which I want to rewrite to clojure. But I am stuck this part:

// HTTP request handling loop.
(async () => {
  for await (let requestData of httpServer.listener('request')) {
    expressApp.apply(null, requestData);

// SocketCluster/WebSocket connection handling loop.
(async () => {
  for await (let {socket} of agServer.listener('connection')) {
    // Handle socket connection.


I tried your code, but it says (.listener http "request") is not an asyncIterable, I guess this is right. How can I implement this node snippet?

p4ulcristian14:03:28 How would you do this in interop?

(async function() {
   for await (let num of asyncIterable) {


Clojurescript doesn't have any constructs that directly translate to for await. My code should work with any async iterable object, but if you want to use that particular syntax you'll have to do it in JavaScript itself.


@U1YTC9FU5 I did forget one important detail, Symbol.asyncIterator points to a function that returns the iterator. I fixed my code so that it handles this correctly


I went to look at what that .listener method returns, it does have a Symbol.asyncIterator defined so it should work


the implementation is provided by the server class, so don't worry about the method stub in that class file


Thank you very much for giving this your time! I have an error though. consumable-stream tries to use createConsumer on nil. This is the error:

SHADOW import error /Users/paulcristianmartin/FaasKitchen/paulhub-wss/minimal-shadow-cljs-nodejs/.shadow-cljs/builds/app/dev/out/cljs-runtime/server.main.js

JS reload failed TypeError: Cannot read property 'createConsumer' of null

    at output (/Users/paulcristianmartin/FaasKitchen/paulhub-wss/node_modules/consumable-stream/index.js:23:12)
    at Function.cljs$core$IFn$_invoke$arity$variadic (/Users/paulcristianmartin/FaasKitchen/paulhub-wss/minimal-shadow-cljs-nodejs/.shadow-cljs/builds/app/dev/out/cljs-runtime/server/main.cljs:152:12) 


I guess because of this part

[Symbol.asyncIterator]() {
    return this.createConsumer();


it's just strange to see that if your previous example worked, because that's the same function regular JS calls if you do for...await. Could you try in javascript

myListener = server.listener('request');


if that returns an error as well, socketcluster has some kind of bug that's not spec-compliant


this is javascript code, where do you want me to try it? in a separate node application?


you could also try passing the result from .listener directly to my async-iter-next function with the proper arguments, as it has the .next method as well


I did exactly that:

(def one-chan (async/chan))
(async-iter-chan one-chan (.listener http-server "request"))


I tried it in a separate node project, in the socketcluster one, I pasted what told me, it works.


try this (async-iter-next one-chan (.listener http-server "request") true js/console.error)


async-iter-next instead of chan


yes, it has no problem, no output


the aget starts the function createConsumer, but doesn't have this ?


aget just expands to JS code like this (aget thing foo) => thing[foo]


so (aget listener js/Symbol.asyncIterator) will return the function that makes an async iterator (eg listener[Symbol.asyncIterator])


if there's no errors now, try taking stuff from that channel (go (js/console.log (<! one-chan)))


I have to write it in a go block, doesn't work with def for me.


yeah sorry, forgot about that


did you manage to get anything?


  (println (<! one-chan)))

(async-iter-next one-chan 
 (.listener http-server "request") 
 true js/console.error)


this is how I tried


this is much harded then I anticipated. Till now I only dealt with clojurescript SPA-s and some clojure backend. Never needed more the core.async


yeah, I think this is just some bad interop getting in the way. I got one more thing to try and I think I'm out of tricks from there

(defn async-iter-chan
  "Take an async iterable `iter-obj` and push it to channel `output`. Closes
  `output` when the iterable is exhausted. Provide a false `:close?` argument to
  leave the output open."
  [output iter-obj & {:keys [close? rejected] :or {close? true rejected js/console.error}}]
     output (js-invoke iter-obj js/Symbol.asyncIterator) close? rejected)


I changed that iter-chan function to use this


so the js-invoke should expand to exactly iter_obj[Symbol.asyncIterator]()


idk why the other stuff wouldn't work, but hopefully this does


this seems to work, at least I don't see any errors


bless you man, I hope I manage from here on 😄


no problem, just glad to see people using clojure(script)!


from 5 years now, want to keep it that way! Still many things to learn, especially about interop.


it's pretty sweet overall, but nasty stuff like this bindings do tend to screw it up. but that's true of javascript as well


in any case, doing (async-iter-chan ...) is about as close as you'll get to for...await using core.async. Feel free to dm me if you hit another related roadblock.


Thank you, I will!


It had one more little error, for anyone who will need it later

(and (not (.-done next-elem)) (>! output (.-value next-elem)))


(and (not (.-done next-elem)) (async/put! output (.-value next-elem)))


hmmm, it's fine if that works for your use case, but I did >! so the go block would park until the value was taken. If you do use put! instead you'll get as many puts as your iterable will produce without waiting for takes. You'll need a buffered channel to do that without a problem.


Oh, I thought that's the reason that I saw only the first request in my log, my bad.


I see, now that I go-loop through the channel it works alright. What about parallelism? Will be okay for a lot of clients? How much can it handle?


I think asyncIterable specifies a need for internal buffers when there's more than one consumer, so it should work OK. Plus javascript is single-threaded, so only one consumer can be running at any given moment in time.


Sorry @U1YTC9FU5 was talkin some mad lies that I deleted. If you want to consume N elements at once, just use my provided code with a buffered channel. >! only parks when the buffer is full, so it will take N elements at once given a buffer of size N


I didn't see those, but thanks, now it's clearer


Is this valid? When I refresh or leave the page it goes in an infinite loop of null events. Can I brake out the loop?

(go-loop [x 1]
  (let [data (<! wss-connections-chan)]
       ;listener on socket of this connection
         (.receiver (.-socket data) "simple-code"))
       (recur (inc x))))


I'm guessing the iterable might not actually be setting done correctly when the socket closes. If there's a callback for when the serverside of the socket closes, you can close the async iterator channel there.


You'd need to create an intermediate channel that you pipe to your output eg

(let [client-receive (async/chan)]
    (.receiver (.-socket data) "simple-code"))
  ;; You'd need to use the right callback here, just doing a strawman placeholder
  (.-onClose data #(async/close! client-receive))
  ;; I'm passing false at the end to prevent wss-communication-chan from closing
  (async/pipe client-receive wss-communication-chan false)
  ;; of the code here)


maybe a simpler solution would be to close the channel inside async-iter-next when you get a nil, but that's probably some kind of error condition you'd want to deal with


no, this solution is perfect, thank you very much. You saved my project !




on leaving the page I've got null instead of nil, and couldn't (= js/null (.-value elem))


and it looks way much cleaner this way 🙂


null and nil are the same value, they just have different names between js and cljs (like in regular clojure/java). Glad it works!


I decided to clean this up and make a gist, would be great if you can throw some usage onto it


I finish testing it and I will make a repo for the socketcluster clojure translation, and mention it in a comment, if that's what you mean by usage.


yeah, put a link to your repo in the gist, it would help other people out


I totally agree. I make the front-end part aswell with this solution, then I'll push it, with some example buttons and stuff.


I am almost ready, I got stuck again at .setMiddleware()

(let [client-receive (async/chan)]
              (.-MIDDLEWARE_INBOUND ag-server)
              (fn [middleware]
This works, with multiple clients also, but if I refresh the page or leave it, the events stops working.


oh yes, I did it, I am so happy I was able to figure it out

  (.-MIDDLEWARE_INBOUND ag-server)
  (fn [middleware]
     (let [client-receive (async/chan)]
          middleware)                                   (async/pipe 
Of course with the help of your examples :D


Anyone know how to use macros from an external, depended upon library with cljs.js/eval-str ? Is it possible to do it without using the source string? Ie, I want to use the library inside cljs.js/eval-str how do I do this?

(cljs.js/eval-str state
(ns myns (:require-macros [javelin.core]))
(def xx (javelin.core/cell 123)) 
@xx ;;works
;;(def yy (javelin.core/cell= (+ xx 123))) ;;cell= is a macro
;;@yy ;;doesn't work
                  {:verbose    true
                   :source-map true
                   :eval       cljs.js/js-eval 
                  (fn [{:keys [error] :as res}]
                    (if error
                        (println error)
                        (println (.. error -cause -stack)))
                      (println res))))


anybody working with three.js & shaders / cljs / reagent? I've kind of gotten a hang of it but I'm still looking for guidance on how you've packaged your shaders and how you are manipulating the values? seems obvious to put the manipulatives in an atom but if there are any examples on how you've maybe structured the manipulation code and multiple shaders together, I'd be interested in taking a look


this is maybe too far from your model, but I ported a few react-three-fiber demos to cljs: it is using modern react, so all shader updates would be implemented in react hooks - but none of ported demos needs that


also using shadow-cljs so I’m able to keep shader sources as separate files and embed them into compiled cljs via inline macro:


you could do it in clojure macro as well, but this method is compilation-cache friendly


thanks @U08E3BBST last time I looked at the react-fiber not to mention the cljs pieces, it didn't look quite ready for primetime. shader updates in react hooks sounds great though. can you say anything about the performance compared to the stack renderer, perhaps especially related to three.js?


unfornutaly I cannot, this is the only toy project I have at the moment, and I’m new to three.js


alright, thanks anyway. I'll keep your project in mind