clojurescript

maybenot 2025-03-13T14:11:32.099749Z

What’s the suggested way to deal with async interables from cljs? I’m using core async so was looking something like <!p but found an open issue Maybe other lib?

mitchelkuijpers 2025-03-13T14:14:43.282729Z

We have had a lot of success with https://github.com/funcool/promesa their p/let implementation solves so much pain for us

maybenot 2025-03-13T14:17:37.928459Z

Great, thanks! Didn’t know they support iterables

mitchelkuijpers 2025-03-13T14:18:27.286049Z

Oh wait me neither πŸ˜›

πŸ˜… 1
cormacc 2025-03-13T14:24:44.567729Z

I ran into this a little while back and stole other peoples work (linked in source here)... https://github.com/cormacc/cljserial/blob/master/src/stack/apis/async_iterator.cljs And a usage example here.... https://github.com/cormacc/cljserial/blob/master/src/stack/apis/opfs.cljs#L50

πŸ”₯ 1
p-himik 2025-03-13T14:27:52.258479Z

I would absolutely just go the simplest route of interop.

(-> async-iter
    (.next)
    (.then (fn iterate [item]
             (do-stuff-to item)
             (-> async-iter
                 (.next)
                 (.then iterate)))))
Or something like that, haven't tested it. I tend to avoid core.async in CLJS at all costs.

πŸ”₯ 1
p-himik 2025-03-13T14:29:07.566429Z

Ah, have to check for (.-done item), and item is not actually the item. The actual item is apparently (.-value item).

mitchelkuijpers 2025-03-13T14:29:30.987789Z

@p-himik You and me both, I will only reach for core.async if there is really good reason to do that

p-himik 2025-03-13T14:30:18.195009Z

But I also avoid Promesa and other other conveniences. :) I've been badly bitten before and the benefit of a thin wrapper isn't worth it.

mitchelkuijpers 2025-03-13T14:31:52.565879Z

Our backends are also nodejs and without some p/let macros our code would get very unwieldy very fast

mitchelkuijpers 2025-03-13T14:32:00.899899Z

But fair enough

p-himik 2025-03-13T14:35:34.236039Z

Pestered ChatGPT enough to get me a full (but still untested) function:

(defn process-async-iterator [async-iterator callback]
  (letfn [(handle-next [result]
            (let [done (.-done result)
                  value (.-value result)]
              (when-not done
                (callback value)
                (-> (.next async-iterator)
                    (.then handle-next)))))]
    (-> (.next async-iterator)
        (.then handle-next))))

mitchelkuijpers 2025-03-14T14:31:48.663069Z

Hehe squint makes this so much better

maybenot 2025-03-14T15:21:41.575829Z

If I have async iterator it works the same way as generator? Simple doseq and await on item?

borkdude 2025-03-14T15:25:48.427089Z

in squint yes, but in normal CLJS no, since CLJS doesn't support await

borkdude 2025-03-14T15:26:14.967279Z

promesa has p/doseq though (which I contributed 😎 )

πŸ”₯ 2
borkdude 2025-03-14T15:29:16.486759Z

I guess you could also just do (js/Promise.all (async-generator-fn)) and then use .then to do whatever you want with the array of values