cljs / src / ird / async.cljs
289 words
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
(ns ird.async
  "The channel contract every ird function follows, plus the tools to work
  with it.

  Every API function returns a core.async promise-chan that delivers exactly
  one value: the parsed response map, or an ExceptionInfo describing the
  failure (see ird.errors). Nothing is ever thrown out of an API function;
  errors travel as values so a `go` block can decide what to do with them:

    (go (let [r (<! (domains/check c \"example.ro\"))]
          (if (error? r) (handle r) (use r))))

  Inside a go block `<?` takes and rethrows errors, so ordinary try/catch
  works; `go-try` is a go block that catches whatever its body throws and
  delivers it as a value — write your own helpers with it. Outside go blocks
  use `->promise` (or cljs.core.async/take!)."
  (:require-macros [ird.async])
  (:require [cljs.core.async :as async]))

(defn error?
  "True when V is an error value (any js/Error, which includes ExceptionInfo)."
  [v]
  (instance? js/Error v))

(defn throw-err
  "Throw V when it is an error value, else return it. `<?` expands to this."
  [v]
  (if (error? v) (throw v) v))

(defn promise->chan
  "Adapt a JS Promise to ird's channel contract: a promise-chan delivering
  the resolution (nil closes the channel), or the rejection reason as a value
  — wrapped in a js/Error when it is not one already."
  [p]
  (let [c (async/promise-chan)]
    (.then p
           (fn [v] (if (nil? v) (async/close! c) (async/put! c v)))
           (fn [e] (async/put! c (if (error? e)
                                   e
                                   (js/Error. (str "Promise rejected: " e))))))
    c))

(defn ->promise
  "Adapt an ird channel to a JS Promise: resolves with the delivered value,
  rejects when that value is an error — for the edge of a :node-library
  build, where JavaScript callers expect promises."
  [ch]
  (js/Promise. (fn [resolve reject]
                 (async/take! ch (fn [v] (if (error? v) (reject v) (resolve v)))))))

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/cljs.git