Skip to content

Instantly share code, notes, and snippets.

@knubie
Created February 15, 2020 00:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save knubie/d0fbc8fc3819d22d2188b257a5f8de75 to your computer and use it in GitHub Desktop.
Save knubie/d0fbc8fc3819d22d2188b257a5f8de75 to your computer and use it in GitHub Desktop.

(put! ch val) - Puts a value onto a channel, doesn't block at all. (>! ch val) - Puts a value onto a channel, "blocks" in a go block (parks). (>!! ch val) - Puts a value onto a channel, blocks. Not available in js.

(take! ch cb) - Takes a value from a channel, doesn't block at all. Take a callback fn. (<! ch) - Takes a value from a channel, "blocks" in a go block (parks). (<!! ch) - Takes a value form a channel, blocks. Not available in js.

Let's compare core.async with three prominent async strategies in Javascript:

  1. Callbacks
  2. Promises
  3. async/await

First, we'll look at call backs.

get('https://my.api/foo', (res) => {
  get('https://my.api/bar/' + res.name, (res2) => {
    alert(res2);
  })
});

Let's see what this would look like if get returned a promise.

get('https://my.api/foo')
  .then((res) => get('https://my.api/bar/' + res.name))
  .then((res) => alert(res));

Inside of an async function, we can use the special await keyword to "block" only inside of the async function. This allows us to write asynchronous code in a synchronous style that only blocks within the context of the function.

async function doSomething () {
  let res  = await get('https://my.api/foo')
  let res2 = await get('https://my.api/bar/' + res.name) 
  alert(res2)
}

Let's assume that we're using the callback version of get here within cljs.

(defn our-get [addr]
  ;; First, make a channel to store the result in.
  (let [channel (chan 0)]
    ;; Store the result in the channel using `put!`, which doesn't block at all.
    (js/get addr #(put! channel %))
    ;; Finally, return the channel.
    channel))

;; The `go` block works very similarly to the `async` keyword in javascript.
;; Calling `<!` (the "parking" version of `take!`, will "block" (ie. "park")
;; *only within the context of the go block*.
(go
  (let [res  (<! (get 'https://my.api/foo'))
        res2 (<! (get (str "https://my.api/bar/" res.name)))]
    (js/alert res2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment