Search code examples
clojurescript

How to return a promise from a go block?


The question is how to send to a nodejs app the result of a go block

  • i found a solution with callback
  • but i need a solution with promise

Promise solution?

Clojurescript app

(defn foo []  
  (go 1))

;;how to change foo,wrap to promise?, so node app can await to get  the 1
;;i used 1 for simplicity in my code i have something like
;;(go (let [x (<! ...)] x))

Node app

async function nodefoo() {
  var x = await foo();
  console.log(x);     // i want to see 1
}

Callback solution (the one that works now)
So far i only found a way to pass a cb function, so this 1 goes back to node.js app

Clojurescript app

(defn foo1 [cb]
  (take! (go 1)
         (fn [r] (cb r))))

Node app

var cb=function () {....};
foo1(cb);   //this way node defined cb function will be called with argument 1

But i dont want to pass a callback function, i want node.js to wait and get the value.
I want to return a promise.


Solution

  • This function takes a channel and returns a Javascript Promise that resolves with the first value the channel emits:

    (defn wrap-as-promise
      [chanl]
      (new js/Promise (fn [resolve _] 
                        (go (resolve (<! chanl))))))
    

    Then to show usage:

    (def chanl (chan 1))
    (def p (wrap-as-promise chanl))
    (go
      (>! chanl "hello")
      (.then p (fn [val] (println val))))
    

    If you compile that and run it in your browser (assuming you called enable-console-print!) you'll see "hello".