(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:
- Callbacks
- Promises
- 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))