Liking cljdoc? Tell your friends :D

jtk-dvlp.async

Drop-in replacements for core.async that propagate errors.

In plain core.async an exception thrown inside a go block is swallowed: the block's channel just closes and the caller sees nil. Here the exception travels as a value on the channel and is thrown again by <! in whichever go block takes it. Inside a go that throw is caught once more and becomes that block's result — so an error keeps climbing the go block stack until someone catches it, the way it would in synchronous code.

Stack traces are stitched across the boundary, so a trace shows both the block that failed and the one that asked for the value. See athrow.

Everything in this namespace propagates errors that way, and an exception travels as itself: the class, message and ex-data that were thrown are the ones caught. Only a thrown value that is no exception at all — which ClojureScript allows — is lifted into an ExceptionInfo carrying {:code :unknown, :error x}.

WATCHOUT: Do not mix these with clojure.core.async. Propagation only works because the error is an ordinary value on the channel — a plain core.async/<! in between takes that value silently, and the error is gone with nothing left to notice it by.

Drop-in replacements for `core.async` that propagate errors.

In plain `core.async` an exception thrown inside a `go` block is
swallowed: the block's channel just closes and the caller sees
`nil`. Here the exception travels as a *value* on the channel and is
thrown again by `<!` in whichever go block takes it. Inside a `go`
that throw is caught once more and becomes that block's result — so
an error keeps climbing the go block stack until someone catches it,
the way it would in synchronous code.

Stack traces are stitched across the boundary, so a trace shows both
the block that failed and the one that asked for the value. See
`athrow`.

Everything in this namespace propagates errors that way, and an
exception travels as itself: the class, message and `ex-data` that
were thrown are the ones caught. Only a thrown value that is no
exception at all — which ClojureScript allows — is lifted into an
`ExceptionInfo` carrying `{:code :unknown, :error x}`.

WATCHOUT: Do not mix these with `clojure.core.async`. Propagation
only works because the error is an ordinary value on the channel — a
plain `core.async/<!` in between takes that value silently, and the
error is gone with nothing left to notice it by.
raw docstring

->exceptionclj/s

(->exception message code x)

Turns x into something that can travel a channel as an error.

Anything throwable is handed back untouched — the caller built it and means it. Anything else is lifted into an ExceptionInfo with code and the value under :error.

WATCHOUT: That second case is why this exists, and it is not a JVM concern. JavaScript lets you throw 42, and a promise may reject with anything at all. Such a value must be lifted, or it would arrive on the channel indistinguishable from a result and the error would vanish without a sound.

NOTE: The lifted value goes under :error in the ex-data, not into the cause. clojure.core/ex-info demands a Throwable there and throws a ClassCastException on anything else, while ClojureScript takes whatever it is given — the same code blew up on one platform and quietly worked on the other.

Turns `x` into something that can travel a channel as an error.

Anything throwable is handed back untouched — the caller built it
and means it. Anything else is lifted into an `ExceptionInfo` with
`code` and the value under `:error`.

WATCHOUT: That second case is why this exists, and it is not a JVM
concern. JavaScript lets you `throw 42`, and a promise may reject
with anything at all. Such a value must be lifted, or it would
arrive on the channel indistinguishable from a result and the error
would vanish without a sound.

NOTE: The lifted value goes under `:error` in the `ex-data`, not
into the `cause`. `clojure.core/ex-info` demands a `Throwable`
there and throws a `ClassCastException` on anything else, while
ClojureScript takes whatever it is given — the same code blew up on
one platform and quietly worked on the other.
sourceraw docstring

<!clj/smacro

(<! ?exp)

Like core.async/<!, but throws the taken value if it is a carried error.

This is what propagates an error up the go block stack: inside a go the throw is caught again and becomes that block's result, so the error keeps climbing until someone catches it.

WATCHOUT: Catch what was actually thrown. Since exceptions travel as themselves, a catch ExceptionInfo no longer sees a foreign exception — that needs Exception (JVM) or :default (cljs).

Like `core.async/<!`, but throws the taken value if it is a
carried error.

This is what propagates an error up the go block stack: inside a
`go` the throw is caught again and becomes that block's result,
so the error keeps climbing until someone catches it.

WATCHOUT: Catch what was actually thrown. Since exceptions travel
as themselves, a `catch ExceptionInfo` no longer sees a foreign
exception — that needs `Exception` (JVM) or `:default` (cljs).
sourceraw docstring

<!!clj/smacro

(<!! ?exp)

Like core.async/<!!, but throws the taken value if it is a carried error. Blocks the calling thread.

Clojure only — ClojureScript has no blocking take.

Like `core.async/<!!`, but throws the taken value if it is a
carried error. Blocks the calling thread.

Clojure only — ClojureScript has no blocking take.
sourceraw docstring

<?clj/smacrodeprecated

(<? sync-or-async-exp)

Deprecated, use <?! — it is the same thing under a name that says how it relates to <! and <!!.

Kept because it is public API and removing it would break callers.

Deprecated, use `<?!` — it is the same thing under a name that
says how it relates to `<!` and `<!!`.

Kept because it is public API and removing it would break
callers.
sourceraw docstring

<?!clj/smacro

(<?! sync-or-async-exp)

Like <!, but takes a value that may or may not be a channel: a channel is taken from, anything else is passed through unchanged.

For APIs that return either a ready value or a channel, so the caller does not have to ask which.

Like `<!`, but takes a value that may or may not be a channel: a
channel is taken from, anything else is passed through unchanged.

For APIs that return either a ready value or a channel, so the
caller does not have to ask which.
sourceraw docstring

<?!!clj/smacro

(<?!! sync-or-async-exp)

Like <!!, but takes a value that may or may not be a channel. Blocks the calling thread.

Clojure only — ClojureScript has no blocking take.

Like `<!!`, but takes a value that may or may not be a channel.
Blocks the calling thread.

Clojure only — ClojureScript has no blocking take.
sourceraw docstring

allclj/s

(all chs)

Waits for all channels chs and yields a vector of their values, in the order of chs. Alias for (map vector chs).

Propagates the first error among them. With no channels the result is [].

Waits for all channels `chs` and yields a vector of their values, in
the order of `chs`. Alias for `(map vector chs)`.

Propagates the first error among them. With no channels the result
is `[]`.
sourceraw docstring

amapclj/s

(amap <f & xs)

Like clojure.core/map, but <f is asynchronous and returns a channel. Calls may overtake each other and, in Clojure, run in parallel; ClojureScript is single-threaded and only interleaves them. The results keep the order of xs either way.

Yields a channel with the vector of results. Propagates errors. A nil among the results is an ordinary value and keeps its place.

See smap when the calls must not overlap.

Like `clojure.core/map`, but `<f` is asynchronous and returns a
channel. Calls may overtake each other and, in Clojure, run in
parallel; ClojureScript is single-threaded and only interleaves
them. The *results* keep the order of `xs` either way.

Yields a channel with the vector of results. Propagates errors. A
`nil` among the results is an ordinary value and keeps its place.

See `smap` when the calls must not overlap.
sourceraw docstring

apostwalkclj/s

(apostwalk <f form)

Like clojure.walk/postwalk, but <f is asynchronous and returns a channel. Visits every node of form innermost first, so <f sees a node only after its children were replaced.

Calls may overtake each other and, in Clojure, run in parallel. Yields a channel with the walked form. Propagates errors.

Like `clojure.walk/postwalk`, but `<f` is asynchronous and returns
a channel. Visits every node of `form` innermost first, so `<f` sees
a node only after its children were replaced.

Calls may overtake each other and, in Clojure, run in parallel.
Yields a channel with the walked form. Propagates errors.
sourceraw docstring

aprewalkclj/s

(aprewalk <f form)

Like clojure.walk/prewalk, but <f is asynchronous and returns a channel. Visits every node of form outermost first, so whatever <f puts in place of a node is walked as well.

Calls may overtake each other and, in Clojure, run in parallel. Yields a channel with the walked form. Propagates errors.

Like `clojure.walk/prewalk`, but `<f` is asynchronous and returns a
channel. Visits every node of `form` outermost first, so whatever
`<f` puts in place of a node is walked as well.

Calls may overtake each other and, in Clojure, run in parallel.
Yields a channel with the walked form. Propagates errors.
sourceraw docstring

areduceclj/s

(areduce <f init coll)

Like clojure.core/reduce, but <f is asynchronous and returns a channel. Reduces coll into init, waiting for each step.

Yields a channel with the result. Propagates errors. A nil or false in coll is an ordinary item and is reduced like any other.

Like `clojure.core/reduce`, but `<f` is asynchronous and returns a
channel. Reduces `coll` into `init`, waiting for each step.

Yields a channel with the result. Propagates errors. A `nil` or
`false` in `coll` is an ordinary item and is reduced like any
other.
sourceraw docstring

athrowclj/smacro

(athrow e)

Throws e, after extending its stack trace with the current one.

Without this the trace would end where the go block's thread began, and the caller that asked for the value would be invisible — the very context one needs to make sense of the error. The two halves are separated by an ASYNC_BOUNDARY marker: above it the frames of the block that failed, below it the frames of the block that took the value.

Used by <!; rarely needed directly.

Throws `e`, after extending its stack trace with the current one.

Without this the trace would end where the go block's thread
began, and the caller that asked for the value would be invisible
— the very context one needs to make sense of the error. The two
halves are separated by an `ASYNC_BOUNDARY` marker: above it the
frames of the block that failed, below it the frames of the block
that took the value.

Used by `<!`; rarely needed directly.
sourceraw docstring

awalkclj/s

(awalk <inner <outer form)

Like clojure.walk/walk, but <inner and <outer are asynchronous and return channels. Calls may overtake each other and, in Clojure, run in parallel.

Yields a channel with the walked form. Propagates errors.

Usually reached through apostwalk or aprewalk.

Like `clojure.walk/walk`, but `<inner` and `<outer` are
asynchronous and return channels. Calls may overtake each other and,
in Clojure, run in parallel.

Yields a channel with the walked form. Propagates errors.

Usually reached through `apostwalk` or `aprewalk`.
sourceraw docstring

chainclj/s

Alias for smap.

Alias for `smap`.
sourceraw docstring

chan?clj/s

(chan? x)

Is x a core.async channel?

Is `x` a `core.async` channel?
sourceraw docstring

consume!clj/s

(consume! ch f)

Calls f for every value on channel ch. Returns nil right away; the consuming runs on its own — on a future in Clojure, in a go block in ClojureScript.

Ends on a closed channel and on a thrown exception. A false in the stream is an ordinary value and is passed to f like any other.

Calls `f` for every value on channel `ch`. Returns `nil` right away;
the consuming runs on its own — on a `future` in Clojure, in a go
block in ClojureScript.

Ends on a closed channel and on a thrown exception. A `false` in
the stream is an ordinary value and is passed to `f` like any
other.
sourceraw docstring

exception?clj/s

(exception? x)

Is x a carried error, i.e. anything the platform can throw?

On the JVM a Throwable, in ClojureScript a js/Error. Everything throwable travels as itself, so this is the same question as "may <! throw this again?".

WATCHOUT: This is also the reason an exception cannot be a payload. A value that happens to be an exception object is read as an error here, not as a result. Wrap it if you mean it as data.

Is `x` a carried error, i.e. anything the platform can throw?

On the JVM a `Throwable`, in ClojureScript a `js/Error`. Everything
throwable travels as itself, so this is the same question as "may
`<!` throw this again?".

WATCHOUT: This is also the reason an exception cannot be a payload.
A value that happens to be an exception object is read as an error
here, not as a result. Wrap it if you mean it as data.
sourceraw docstring

goclj/smacro

(go & body)

Like core.async/go, but an exception thrown in body becomes the block's result instead of being swallowed.

The exception travels as itself — same class, same message, same ex-data. Only a thrown value that is not an exception at all is lifted into one, which ClojureScript allows. Take the result with <! to have it thrown again.

WATCHOUT: On the JVM an Error is deliberately not caught. A StackOverflowError or OutOfMemoryError says the machine is in trouble, not that this computation failed; handing it on as an ordinary channel value would let the program carry on as if it could. It escapes into core.async's thread instead, which closes the channel. ClojureScript has no such distinction — everything there descends from js/Error.

Like `core.async/go`, but an exception thrown in `body` becomes
the block's result instead of being swallowed.

The exception travels as itself — same class, same message, same
`ex-data`. Only a thrown value that is not an exception at all is
lifted into one, which ClojureScript allows. Take the result with
`<!` to have it thrown again.

WATCHOUT: On the JVM an `Error` is deliberately *not* caught. A
`StackOverflowError` or `OutOfMemoryError` says the machine is in
trouble, not that this computation failed; handing it on as an
ordinary channel value would let the program carry on as if it
could. It escapes into core.async's thread instead, which closes
the channel. ClojureScript has no such distinction — everything
there descends from `js/Error`.
sourceraw docstring

go-loopclj/smacro

(go-loop bindings & body)

Like core.async/go-loop, with the error handling of go.

Like `core.async/go-loop`, with the error handling of `go`.
sourceraw docstring

intoclj/s

(into coll ch)

Like core.async/into, but propagates errors: an error carried on ch becomes the result instead of ending up in the collection.

Like `core.async/into`, but propagates errors: an error carried on
`ch` becomes the result instead of ending up in the collection.
sourceraw docstring

mapclj/s

(map f chs)

Like core.async/map, but propagates errors: if any channel in chs carries an error, or f throws, that error becomes the result instead of being lost.

With no channels at all the result is (f), the same answer clojure.core gives for folding over nothing — (map + []) yields 0, (map vector []) yields [].

Like `core.async/map`, but propagates errors: if any channel in
`chs` carries an error, or `f` throws, that error becomes the result
instead of being lost.

With no channels at all the result is `(f)`, the same answer
`clojure.core` gives for folding over nothing — `(map + [])` yields
`0`, `(map vector [])` yields `[]`.
sourceraw docstring

reduceclj/s

(reduce f init ch)

Like core.async/reduce, but propagates errors: an error carried on ch, or thrown by f, ends the reduction and becomes the result.

Like `core.async/reduce`, but propagates errors: an error carried on
`ch`, or thrown by `f`, ends the reduction and becomes the result.
sourceraw docstring

smapclj/s

(smap <f & xs)

Like clojure.core/map, but <f is asynchronous and returns a channel. Calls happen strictly one after another in the order of xs, each waiting for the one before it.

Yields a channel with the vector of results. Propagates errors. Stops when the shortest collection runs out, like clojure.core/map; a nil or false among the elements is an ordinary value.

See amap for the variant that may run in parallel.

Like `clojure.core/map`, but `<f` is asynchronous and returns a
channel. Calls happen strictly one after another in the order of
`xs`, each waiting for the one before it.

Yields a channel with the vector of results. Propagates errors.
Stops when the shortest collection runs out, like
`clojure.core/map`; a `nil` or `false` among the elements is an
ordinary value.

See `amap` for the variant that may run in parallel.
sourceraw docstring

threadclj/smacro

(thread & body)

Like core.async/thread, with the error handling of go. Runs body on a real thread, so it may block.

Clojure only.

Like `core.async/thread`, with the error handling of `go`. Runs
`body` on a real thread, so it may block.

Clojure only.
sourceraw docstring

thread-callclj

(thread-call f)
(thread-call f workload)

Like core.async/thread-call, with the error handling of go: an exception from f becomes the channel's value instead of escaping into the thread pool unnoticed.

workload says what f does, so core.async can route it to the right pool — :io, :compute or :mixed (the default).

WATCHOUT: The workload argument needs core.async 1.8.730 or newer. It is the consumer's version that counts, not the one pinned here — a :dependencies entry in a library is routinely overridden downstream, and an older core.async answers every single call with an ArityException.

Clojure only.

Like `core.async/thread-call`, with the error handling of `go`:
an exception from `f` becomes the channel's value instead of
escaping into the thread pool unnoticed.

`workload` says what `f` does, so core.async can route it to the
right pool — `:io`, `:compute` or `:mixed` (the default).

WATCHOUT: The workload argument needs core.async 1.8.730 or
newer. It is the consumer's version that counts, not the one
pinned here — a `:dependencies` entry in a library is routinely
overridden downstream, and an older core.async answers every
single call with an `ArityException`.

Clojure only.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close