conquerant
async/await for Clojure
A lightweight Clojure wrapper around ForkJoinPool and CompletableFuture
for concurrency that is simple and easy.
Why
core.async
- is very powerful, but quite low-level by design
- and the source is hard to follow
- we don't always want this kind of power
- doesn't allow using custom threadpools
- breaks on function boundaries
- breaks emacs
Usage
;; Async HTTP Exaxmple
;; ===================
(refer-clojure :exclude '[await promise])
(require '[clj-http.client :as client]
'[conquerant.core :refer [async await promise]])
(def url "https://gist.githubusercontent.com/divs1210/2ce84f3707b785a76d225d23f18c4904/raw/2dedab13201a8a8a2c91c3800040c84b70fef2e2/data.edn")
(defn fetch [url]
(promise [resolve]
(client/get url
{:async? true}
(fn [response]
(resolve [response nil]))
(fn [error]
(resolve [nil error])))))
(async
(let [[response error] (await (fetch url))]
(if error
(println "Error:" (.getMessage error))
(println "Response Body:" (:body response)))))
(println "fetching asynchronously...")
;; => fetching asynchronously...
;; => Response Body: {:result 1}-
promise- gets value out of callback
- runs body on a lightweight thread, returning a
CompletableFuture - can be resolved from outside via
complete - can be
derefed:@(promise [resolve] (resolve :hi)) - can run on a custom
ExecutorServiceusingwith-async-executor
-
async- runs body on a lightweight thread
- can wrap
defnandfnforms - supports variadic versions
(async (defn f ([a] (inc a)) ([a b] (* a b))))
- any other expression, returning a
CompletableFuture(promise)
@(async [1 2]) ;; => [1 2]
- can wrap
- can run on a custom
ExecutorServiceusingwith-async-executor
- runs body on a lightweight thread
-
await- pauses the lightweight thread till the given promise is complete
- can only be used in
asyncletbindings- normal
letblock anywhere inside anasyncblock - every
letblock with a call toawaitreturns aCompletableFuture
- normal
- works across function boundaries
- can timeout like
deref:(await p 1000 :timeout)
-
channels- supports
core.async-like channel operations! (experimental!)
- supports
Walkthrough
Clone this repo, fire up a REPL, and walk through the conquerant walkthrough.
License
Copyright © 2018 Divyansh Prakash
Distributed under the Eclipse Public License either version 1.0.
