Skip to content

Instantly share code, notes, and snippets.

@pangloss
Last active December 27, 2015 15:19
Show Gist options
  • Save pangloss/7346742 to your computer and use it in GitHub Desktop.
Save pangloss/7346742 to your computer and use it in GitHub Desktop.
delay-chan
(ns async
(:require cljs.core.match
[cljs.core.async.impl.protocols :as impl]
[cljs.core.async.impl.channels :as channels]))
(defn delay-chan*
"chan-thunk is something that when deref'd returns a channel. The
first thing that that channel emits will be saved and always returned
by the channel this produces."
[chan-thunk]
(let [state (atom ::start)
c (reify
impl/Channel
(close! [_] (reset! state nil))
impl/ReadPort
(take! [_ fn1]
(let [data @state]
(cond
(= ::start data)
(let [ret
(impl/take! @chan-thunk
(reify
impl/Handler
(active? [_] (impl/active? fn1))
(lock-id [_] (impl/lock-id fn1))
(commit [_]
(let [f1 (impl/commit fn1)]
(fn [result]
(reset! state result)
(f1 result))))))]
(if (and ret (not (nil? @ret)))
(channels/box @ret)
ret))
data (channels/box data)
:else nil))))]
c))
(ns macros)
(defmacro delay-chan [& forms]
`(async/delay-chan* (delay ~@forms)))
(ns usage
(:require async
[cljs.core.async :refer [<! timeout take!]])
(:require-macros [macros :refer [delay-chan]]
[cljs.core.async.macros :refer [go]]))
(let [ch (delay-chan (go (.log js/console "starting work")
(<! (timeout 1000))
"Done!"))]
(.log js/console "Decide whether to do work")
(take! ch #(.log js/console "result: " %))
(take! ch #(.log js/console "result 2: " %)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment