clojurescript

Pepijn de Vos 2025-06-04T10:45:15.774379Z

Is there no standard function for this, turning a channel into a js promise? https://stackoverflow.com/questions/69198810/how-to-return-a-promise-from-a-go-block

thheller 2025-06-04T10:49:21.032539Z

a promise either resolves or rejects once. a channel is a fundamentally different thing, so no there is no generic translation since you kinda need to be specific for behavior you want exactly

Pepijn de Vos 2025-06-04T10:50:26.777619Z

In this case my channel behaves pretty much like a promise, producing a result once it's done

Kirill Chernyshov 2025-06-04T10:53:17.486819Z

sounds like a promise-chan. https://clojure.github.io/core.async/clojure.core.async.html#var-promise-chan However, this is not a direct answer to your question 😞

p-himik 2025-06-04T10:53:21.885089Z

There's no such function built into CLJS.

thheller 2025-06-04T10:53:48.839889Z

(defn take-once [chan]
  (js/Promise.
    (fn [resolve _]
      (async/take! chan
        (fn [val]
          (resolve val))))))

thheller 2025-06-04T10:54:06.852379Z

something like that. take-once from the channel in form of a promise

thheller 2025-06-04T10:54:57.206059Z

could just be (async/take! chan resolve) but being a bit more verbose might make it easier to see what is going on 😛

thheller 2025-06-04T10:56:33.598779Z

but there are many things to consider, like taking from a closed channel or promises that never deliver .. the list is long

thheller 2025-06-04T10:57:47.377009Z

called it take-once because thats clearer in its intent that just chan->promise or so, kinda up to you 🤷

p-himik 2025-06-04T10:59:39.175619Z

Couldn't resist.

1
Pepijn de Vos 2025-06-04T11:00:36.811579Z

So... a go block returns a channel that receives the result right. I basically want to check the go block is "done"

p-himik 2025-06-04T11:01:02.163769Z

You don't need a promise for that.

p-himik 2025-06-04T11:01:09.832289Z

You can just use take! and pass a callback.

Pepijn de Vos 2025-06-04T11:01:44.558229Z

Okay rephrase, I want some piece of JS code that expects an async function to "wait" until the go block is done

dnolen 2025-06-04T11:02:51.066889Z

we have an interop namespace in core.async, and we have helpers for going from promise to chan, but not the other way around. happy to take a patch for that. the docstring should be extra clear about the behavior.

thheller 2025-06-04T11:03:32.435929Z

and what is that JS code calling exactly? does it call into CLJS code directly? does it have a reference to the channel directy? if it has access to the result of take-once when await just works

thheller 2025-06-04T11:04:34.041649Z

(defn some-fn-called-from-js [] (take-once (go 1)))

thheller 2025-06-04T11:04:44.314229Z

const val = await some_fn_called_from_js(); will have val 1

Pepijn de Vos 2025-06-04T11:05:53.069589Z

Yea I think your take once will work

Pepijn de Vos 2025-06-04T11:21:27.433909Z

opaque errors ahead...

SES_UNCAUGHT_EXCEPTION: TypeError: c is undefined
    cljs$core$async$impl$ioc_helpers$take_BANG_ ioc_helpers.cljs:53
    switch__11740__auto__ filestore.cljs:36
    ret_value__11742__auto__ filestore.cljs:36
    nyancad$mosaic$filestore$read_file_$_state_machine__11741__auto____1 nyancad.mosaic.filestore.js:112
    cljs$core$async$impl$ioc_helpers$run_state_machine ioc_helpers.cljs:43
    cljs$core$async$impl$ioc_helpers$run_state_machine_wrapped ioc_helpers.cljs:47
    read_file filestore.cljs:36
    cljs$core$async$impl$dispatch$process_messages dispatch.cljs:27
    onmessage nexttick.js:195
    getNextTickImpl_ nexttick.js:189
    nextTick nexttick.js:59
    cljs$core$async$impl$dispatch$queue_dispatcher dispatch.cljs:37
    cljs$core$async$impl$dispatch$run dispatch.cljs:41
    nyancad$hipflask$get_group hipflask.cljs:53
    cljs$core$IFn$_invoke$arity$3 hipflask.cljs:149
    <anonymous> filestore.cljs:17
    globalEval common.js:455
    evalLoad common.js:1426
    <anonymous> filestore.js:1
lockdown-install.js:1:138390

Pepijn de Vos 2025-06-04T11:22:27.145289Z

It seems "take!" takes a third (optional?) argument called c which.. does that correspond to on-caller?

Pepijn de Vos 2025-06-04T11:23:13.944239Z

the error points here:

(defn take! [state blk ^not-native c]
  (if-let [cb (impl/take! c (fn-handler <<<<<<<
                                   (fn [x]
                                     (ioc/aset-all! state VALUE-IDX x STATE-IDX blk)
                                     (run-state-machine-wrapped state))))]
    (do (ioc/aset-all! state VALUE-IDX @cb STATE-IDX blk)
        :recur)
    nil))

thheller 2025-06-04T11:23:29.988599Z

thats the wrong place to be looking. 100% certain what you are just passing nil into something that shouldn't be nil

thheller 2025-06-04T11:23:56.686149Z

like (take! nil (fn ...))

thheller 2025-06-04T11:24:11.414159Z

guessing filestore.cljs line 36 😉

thheller 2025-06-04T11:25:17.964899Z

take! has 2 arities, so the on-caller? arg isn't relevant (and defaults to true)

Pepijn de Vos 2025-06-04T11:26:49.585969Z

yeah I did something silly, just... not very easy to see inside a go block

thheller 2025-06-04T11:27:29.771459Z

yeah, kind of the reason I never use core.async in CLJS

thheller 2025-06-04T11:27:54.483819Z

I mean async debugging is never easy, but go is just madness