diff --git a/.gitignore b/.gitignore index cbbef5a..2abd0e6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /.cpcache/ /cljs-test-runner-out/ /.clj-kondo/.cache/ +/.lsp/.cache/ diff --git a/src/town/lilac/flex/promise.cljs b/src/town/lilac/flex/promise.cljs index 0e92c73..9558946 100644 --- a/src/town/lilac/flex/promise.cljs +++ b/src/town/lilac/flex/promise.cljs @@ -2,29 +2,70 @@ (:require [town.lilac.flex :as flex])) -(defrecord Resource [state error value loading? fetcher ^:volatile-mutable p] +(defn fetcher-fn [state error value fetcher & args] + (flex/untrack + (case @state + (:unresolved :ready :error) (.then (apply fetcher args) + (fn [x] + (flex/batch + (state :ready) + (value x))) + (fn [e] + (flex/batch + (state :error) + (error e)))) + nil) + (case @state + :unresolved (state :pending) + (:ready :error) (state :refreshing) + nil))) + +(defrecord Resource [state error value loading? fetcher ^:volatile-mutable pr] IDeref (-deref [_] @value) IFn (-invoke [this] - (flex/untrack - (case @state - (:unresolved :ready :error) - (set! p (.then (fetcher) - (fn [x] - (flex/batch - (state :ready) - (value x))) - (fn [e] - (flex/batch - (state :error) - (error e))))) - nil) - (case @state - :unresolved (state :pending) - (:ready :error) (state :refreshing) - nil)) - this)) + (set! pr (fetcher-fn state error value fetcher)) this) + (-invoke [this a] + (set! pr (fetcher-fn state error value fetcher a)) this) + (-invoke [this a b] + (set! pr (fetcher-fn state error value fetcher a b)) this) + (-invoke [this a b c] + (set! pr (fetcher-fn state error value fetcher a b c)) this) + (-invoke [this a b c d] + (set! pr (fetcher-fn state error value fetcher a b c d)) this) + (-invoke [this a b c d e] + (set! pr (fetcher-fn state error value fetcher a b c d e)) this) + (-invoke [this a b c d e f] + (set! pr (fetcher-fn state error value fetcher a b c d e f)) this) + (-invoke [this a b c d e f g] + (set! pr (fetcher-fn state error value fetcher a b c d e f g)) this) + (-invoke [this a b c d e f g h] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h)) this) + (-invoke [this a b c d e f g h i] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i)) this) + (-invoke [this a b c d e f g h i j] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j)) this) + (-invoke [this a b c d e f g h i j k] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k)) this) + (-invoke [this a b c d e f g h i j k l] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k l)) this) + (-invoke [this a b c d e f g h i j k l m] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k l m)) this) + (-invoke [this a b c d e f g h i j k l m n] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k l m n)) this) + (-invoke [this a b c d e f g h i j k l m n o] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k l m n o)) this) + (-invoke [this a b c d e f g h i j k l m n o p] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k l m n o p)) this) + (-invoke [this a b c d e f g h i j k l m n o p q] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k l m n o p q)) this) + (-invoke [this a b c d e f g h i j k l m n o p q r] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k l m n o p q r)) this) + (-invoke [this a b c d e f g h i j k l m n o p q r s] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k l m n o p q r s)) this) + (-invoke [this a b c d e f g h i j k l m n o p q r s t] + (set! pr (fetcher-fn state error value fetcher a b c d e f g h i j k l m n o p q r s t)) this)) (defn resource "Returns a flex source that updates its state based on a promise-returning @@ -40,7 +81,7 @@ `:loading?` - a signal containing true/false whether currently waiting for a promise returned by `fetcher` to fulfill `:fetcher` - the original `fetcher` function - `:p` - the last promise returned by `fetcher`" + `:pr` - the last promise returned by `fetcher`" [fetcher] (let [state (flex/source :unresolved) error (flex/source nil) @@ -49,4 +90,4 @@ (case @state (:pending :refreshing) true false))] - ((->Resource state error value loading? fetcher nil)))) + (->Resource state error value loading? fetcher nil))) diff --git a/test/town/lilac/flex/promise_test.cljs b/test/town/lilac/flex/promise_test.cljs index 94d9af3..2916dc4 100644 --- a/test/town/lilac/flex/promise_test.cljs +++ b/test/town/lilac/flex/promise_test.cljs @@ -11,15 +11,16 @@ (fn [] (res)) ms)))) -(deftest resource +(deftest fetcher-with-noargs-resource (async done (let [r (p/resource (fn [] (-> (sleep 100) (.then (constantly 42))))) + _call-r (r) ; initializing *calls (atom []) s (f/signal (inc @(:value r))) - fx (f/effect [] (swap! *calls conj @s))] + _fx (f/effect [] (swap! *calls conj @s))] (is (= :pending @(:state r))) ;; (is (= :unresolved @(:state r))) (is (= nil @(:value r))) @@ -34,5 +35,35 @@ (is (= [1 43] @*calls)))) (.then done done))))) +(deftest fetcher-with-args-resource + (async + done + (let [r (p/resource (fn [ms] + (-> (sleep ms) + (.then (constantly 42))))) + _call-r (r 200) ; initializing + *calls (atom []) + s (f/signal (inc @(:value r))) + _fx (f/effect [] (swap! *calls conj @s))] + (is (= :pending @(:state r))) + ;; (is (= :unresolved @(:state r))) + (is (= nil @(:value r))) + (is (= nil @(:error r))) + (is (= [1] @*calls)) + ;; (r) + ;; (is (= :pending @(:state r))) + (-> (sleep 101) + (.then (fn [] + (is (= :pending @(:state r))) + (is (= nil @(:value r))) + (is (= [1] @*calls)))) + (.then done done)) + (-> (sleep 201) + (.then (fn [] + (is (= :ready @(:state r))) + (is (= 42 @(:value r))) + (is (= [1 43] @*calls)))) + (.then done done))))) + (comment (t/run-tests))