Fork me on GitHub
#sci
<
2023-04-12
>
sashton13:04:16

Is deref not supported for Promesa promises?

(println (deref (p/promise 1)))

ERROR: No protocol method IDeref.-deref defined for type object: [object Promise]
  {:type :sci/error, :line 8, :column 16, :message "No protocol method IDeref.-deref defined for type object: [object Promise]"
Are the Promesa macros (`p/then` , etc) the only way to operate on the value? (Iā€™m evaling this via Joyride, if that context is useful)

joyride 2
borkdude14:04:44

@U08TWB99B indeed, deref is not supported for promesa promises

borkdude14:04:09

this is not SCI-specific but true in general (for CLJS at least)

sashton14:04:19

makes sense. thanks for confirming

john20:04:41

You could wrap promises with a deref implementation but it'll never be realized in the same synchronous context like your doing there.

john20:04:43

If it's useful for you to be able to deref the promise in a later call, you could do something like this:

(extend-type js/Promise
  ICloneable
  (-clone [p] (.then p)))

(defn derefable-promise [v]
  (let [p (js/Promise.resolve v)
        resolved? (atom false)
        resolved-value (atom nil)
        res-p (-> p
                  (.then (fn [result]
                           (reset! resolved? true)
                           (reset! resolved-value result)
                           result)))]
    (specify
     res-p
     IPending
     (-realized? [_] @resolved?)
     IDeref
     (-deref
      [_]
      (if-let [res @resolved-value]
        res
        res-p)))))

borkdude20:04:20

please don't ;)

john20:04:06

So in a do block, you couldn't print out the value in a blocking way:

(do
  (def p-fetch (js/fetch ""))
  (def p-json (.then p-fetch #(.json %)))
  (def p-iss (.then p-json
                    #(when-let [iss-position (.-iss_position %)]
                       (println :iss-position iss-position)
                       (js->clj iss-position :keywordize-keys true))))
  (def derefable-iss
    (derefable-promise p-iss))
  (println :derefed-iss @derefable-iss))

:derefed-iss #object[Promise [object Promise]]
;=> nil
But you could then later deref it:
@derefable-iss
:iss-position #js {:longitude -48.2400, :latitude 4.6248}
;=> {:longitude "-48.2400", :latitude "4.6248"}

john20:04:54

@U04V15CAJ are you worried about polluting promise for other callers in the environment?

borkdude20:04:38

I think it will just add to the confusion of why it's not a blocking call, that's all

john20:04:41

Right. Maybe promise-delay would be a better word. Or some better name

john20:04:15

promesa must have some delay utility already though

john20:04:19

Ah, promesa's delay gives you a literal time delay

borkdude20:04:31

yes, confusing name ;)

john20:04:47

Oh wait, this is the sci channel šŸ˜† is specify even available in SCI like that?

borkdude20:04:28

@U050PJ2EU The above example won't work in SCI

šŸ‘ 2