Fork me on GitHub

hi there. I use cljs.core.async and have a question. Next code is working well:

  (let [a (<p! (return-promise-fn "a"))
        b (<p! (return-promise-fn "b"))
        c (<p! (return-promise-fn "c"))
        result (into [] a b c)]
    (prn result))) ;; I can get results of promise
I want to change this to like next:
(let [result (map
              (fn [v] (go (<p! (return-promise-fn v))))
              ["a" "b" "c"])]
  (prn result)) ;; I cannot get results of promise
but this code doesn't work as I expect. I understand the occasion is that result is outside the go block, but I have no idea what to fix this problem.


go blocks are not monadic values, cant be chained like promises go blocks are more like light-weight threads that can communicate/coordinate via channels.

(defn promise [v]
  (js/Promise.resolve v))

(def collect-chan (chan 1))

;; launch a go block for collecting results from collect-chan
(go-loop [result []
          item (<! collect-chan)]
  ;; item is not nil as long as channel is open
  (if item
    (recur (conj result item)
           (<! collect-chan))
    ;; when channel is close will print collected values
    (println "collected:" result)))

;; launch n go blocks, one for each promise
;; wait for promise result and then send result to collect-chan
(doseq [p (map promise [1 2 3 4 5])]
  (go (let [prom-result (<p! p)]
        (println "send" prom-result)
        (>! collect-chan prom-result))))

;; close the chan so that go-loop chan break the loop
(close! collect-chan)


dont take my example as a good practice, just showing the idea of how it works:laughing:


also go blocks behave like channel too

(let [ps (map (fn [v]
                  (go (<p! (promise v))))
              ["a" "b" "c"])]
  (go-loop [result []
            [p & ps :as pps] ps]
    (if (seq pps)
      (recur (conj result (<! p))
      (prn result))))


Thank you so much! I try