observe, the hook for reading from outside the page, such as a database
subscription, a poll loop or a query.
It returns pending until the first value arrives, and throws in the render
when what it reads fails: the island renders the error view unless it catches
it. A read is a hold keyed by what it reads, so hooks of an app's own that
read the same thing in one render share it: one resource, one value.
A read that depends on another waits for it with if-loaded.
`observe`, the hook for reading from outside the page, such as a database subscription, a poll loop or a query. It returns `pending` until the first value arrives, and throws in the render when what it reads fails: the island renders the error view unless it catches it. A read is a hold keyed by what it reads, so hooks of an app's own that read the same thing in one render share it: one resource, one value. A read that depends on another waits for it with `if-loaded`.
(if-loaded bindings then)(if-loaded bindings then else)then, with bindings bound as a let's, once every value they bind has
loaded; else else, or pending without one.
(if-loaded [user (observe uid load-user)
orders (observe (:id user) load-orders)]
[:ul (for [o orders] [:li (:title o)])]
[:p "Loading…"])
A value has loaded once it isn't pending. A binding whose expression refers
to one that hasn't isn't evaluated, and hasn't loaded either: a read that
depends on another starts once that one has loaded, never with pending, or
a value taken from it, among its args. One that refers to none is evaluated,
so reads that don't depend on each other start in the same render.
References are found by name, in the expression as written, so a name bound
again inside it still counts, which errs toward waiting. else sees none of
the bindings.
`then`, with `bindings` bound as a `let`'s, once every value they bind has
loaded; else `else`, or `pending` without one.
(if-loaded [user (observe uid load-user)
orders (observe (:id user) load-orders)]
[:ul (for [o orders] [:li (:title o)])]
[:p "Loading…"])
A value has loaded once it isn't `pending`. A binding whose expression refers
to one that hasn't isn't evaluated, and hasn't loaded either: a read that
depends on another starts once that one has loaded, never with `pending`, or
a value taken from it, among its args. One that refers to none is evaluated,
so reads that don't depend on each other start in the same render.
References are found by name, in the expression as written, so a name bound
again inside it still counts, which errs toward waiting. `else` sees none of
the bindings.(observe & args+f)The latest value emitted by a resource shared with every reader of the same
call site and args. The island renders again on each new value.
(observe topic
(fn [emit! topic]
(subscribe-feed topic emit!)))
f opens the resource, as in Missionary's observe: it is called with an
emit! fn and args, only if nobody holds the resource yet.
args.emit! may be called from any thread, from the moment f is called. Only
the latest value is kept: a session renders the value current when it gets
to it, so values in between may never be seen. Once the resource has closed
or failed, emit! does nothing.The call site and args are the resource's key, and so decide who shares it:
every value f depends on must be one of args. f may refer to no local
of the render other than through its params; one that does fails to compile.
args are compared with =, so a value made anew each render, such as a
fresh fn, opens a new resource each render. Pass values and stable references.
If f throws, or its task fails, the resource fails and observe throws its
exception. The island keeps the failure until it unmounts or reads other
args; the next reader opens a new resource.
Given other args, the island holds the new resource and releases the old
one, which lingers before it closes (resource/linger-ms).
If one of args is pending, as another read's value is until it loads, it
returns pending and opens nothing, so a read that depends on another starts
once that one has loaded. A value taken from a pending one, such as
(:id user), is nil, not pending: wait for it with if-loaded.
The same call made again in one render, with equal args, returns the same
value, from the one resource. So a hook of the app's own wrapping observe,
whose every read shares its call site, may be called by several hooks in
one render, each asking of the same data.
The latest value emitted by a resource shared with every reader of the same
call site and `args`. The island renders again on each new value.
(observe topic
(fn [emit! topic]
(subscribe-feed topic emit!)))
`f` opens the resource, as in Missionary's `observe`: it is called with an
`emit!` fn and `args`, only if nobody holds the resource yet.
- It runs on a virtual thread of its own, so it may block while it connects,
and in an empty Scoped scope: the resource belongs to no reader, so it gets
nothing from the render but `args`.
- It returns what undoes it: a fn, called once when the resource closes; or a
Quiescent task, cancelled when the resource closes, whose failure fails the
resource; or nil.
- `emit!` may be called from any thread, from the moment `f` is called. Only
the latest value is kept: a session renders the value current when it gets
to it, so values in between may never be seen. Once the resource has closed
or failed, `emit!` does nothing.
The call site and `args` are the resource's key, and so decide who shares it:
every value `f` depends on must be one of `args`. `f` may refer to no local
of the render other than through its params; one that does fails to compile.
`args` are compared with `=`, so a value made anew each render, such as a
fresh fn, opens a new resource each render. Pass values and stable references.
If `f` throws, or its task fails, the resource fails and `observe` throws its
exception. The island keeps the failure until it unmounts or reads other
`args`; the next reader opens a new resource.
Given other `args`, the island holds the new resource and releases the old
one, which lingers before it closes (`resource/linger-ms`).
If one of `args` is `pending`, as another read's value is until it loads, it
returns `pending` and opens nothing, so a read that depends on another starts
once that one has loaded. A value taken from a pending one, such as
`(:id user)`, is nil, not `pending`: wait for it with `if-loaded`.
The same call made again in one render, with equal `args`, returns the same
value, from the one resource. So a hook of the app's own wrapping `observe`,
whose every read shares its call site, may be called by several hooks in
one render, each asking of the same data.What observe returns until its first value arrives.
What `observe` returns until its first value arrives.
(pending? x)Whether x is pending: a read's value until it has loaded.
Whether `x` is `pending`: a read's value until it has loaded.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |