clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
Jakob Durstberger 2021-05-10T15:56:16.221300Z

Hello, what is the idiomatic way of dealing with promises? I have found the official promise interop guide and <p! but I am not quite sure how to apply that to my scenario. I need to get the access-token from AWS amplify where currentSession returns a promise. I then want to unpack the value of the token pass it along and then make a network call if the promise resolves. Current code:

(defn access-token []
  (-> (.currentSession Auth)
      (.then #(.. % (getAccessToken) (getJwtToken)))))

(defn call [access-token]
  (ajax/GET url
    {:format :json
     :response-format :json
     :keywords? true
     :headers {"Authorization" access-token}
     :handler handle-success
     :error-handler handle-error}))

(defn load-wallet []
  (update-loading true)
  (-> (access-token)
      (.then #(call %))
      (.catch #(handle-error %))))
Is there a better way to write this code.

Karol Wójcik 2021-05-11T07:20:32.228400Z

@niwinz is it possible to switch to bluebird implementation on promesa?

niwinz 2021-05-11T07:21:42.228600Z

You`e`have the sa.impl/ *default-promise*

Karol Wójcik 2021-05-11T07:21:57.228800Z

Something like this?

(ns infrastructure.patch
  (:require
   ["bluebird" :as b]
   [promesa.core :as p]
   [promesa.impl :as impl]))

(impl/extend-promise! js/Promise)
(impl/extend-promise! b/Promise)
(p/set-default-promise! b/Promise)

niwinz 2021-05-11T07:23:16.229Z

For some reason slack trolled me with formating.

niwinz 2021-05-11T07:24:13.229200Z

You will need to set the promesa.impl/**default-promise** dynamic binding

niwinz 2021-05-11T07:24:27.229400Z

with the bluebird Promise class

niwinz 2021-05-11T07:25:17.229700Z

something like

(set! impl/*default-promise* b/Promise)

niwinz 2021-05-11T07:25:48.229900Z

This will make the bluebird the default one

Karol Wójcik 2021-05-11T07:26:50.230100Z

Ok got it. Btw I'm very happy that you removed async-cljs namespace

niwinz 2021-05-11T07:27:30.230400Z

Yeah, the same here, I just want a simple syntactic abstraction without additional deps

Karol Wójcik 2021-05-11T07:32:50.230600Z

As I understand it's possible to just use p/let to simulate async/await alike features.

(-> (p/let [a (some-promise)
                 b (some-promise)]
          (+ a b))
      (p/catch (fn [err] (println "Some arithmetic error")))
What do you think about adding a some sugar like p/try+ p/catch+ p/finally+ so that the asynchronous nature is hidden when using p/let? Actually that would make the whole point of "implement async/await on Clojurescript" invalid since all the futures that async/await provides would be given by promesa.

niwinz 2021-05-11T07:48:38.230800Z

I'm open to have try/catch/finally if someone want to contribute it. We use promesa extensivelly and practically never needed that macros

niwinz 2021-05-11T07:49:06.231Z

I prefer using the standard promise catch mechanism (no macro)

niwinz 2021-05-11T07:50:06.231200Z

this is the reason why that macros arenot available today in promesa

niwinz 2021-05-11T07:52:10.231400Z

additionally, this macros are complex, and introduces a lot of hidden overhead to the code

dpsutton 2021-05-10T16:06:14.221800Z

that's what i would do. promise interop is straight forward

dnolen 2021-05-10T16:08:26.222600Z

@jakob.durstberger writing directly like that is fine

dnolen 2021-05-10T16:08:59.223100Z

if you're going to combine w/ a bunch of other async stuff then <p! becomes useful

dnolen 2021-05-10T16:09:21.223600Z

because otherwise it starts getting annoying IMO

Karol Wójcik 2021-05-10T16:09:39.223700Z

There are multiple options to write this code. You can either use clojure.core.async or some 3rd party library like https://github.com/funcool/promesa or https://github.com/athos/kitchen-async etc. My recommendation is stick to plain promises or maybe use bluebird. I don't use anymore clojure.core.async on Clojurescript side since it 1. produces quite large code upon macroexpansion 2. if you use asynchronous context (node.js AsyncStorage) and fibers then information will leak If all modern browsers would support async/await and Clojurescript would support this syntax then I would probably stick to async/await 😄

Jakob Durstberger 2021-05-10T16:27:35.224300Z

Thanks all 🙂

niwinz 2021-05-10T18:54:37.224800Z

promesa is just a syntactic abstraction over plain promises, so it does not introduces external dependencies more than the promesa itself

niwinz 2021-05-10T18:55:33.225Z

additionally to basic operations it alwo offers let and do like macros for easy compose promises

niwinz 2021-05-10T18:56:12.225200Z

in difference to core.async interop, the result of composition of promises is always an other promise

Karol Wójcik 2021-05-10T19:17:17.226400Z

Yep that is basically the best library for dealing with promises on clojurescript side. Thank you so much for this project!

❤️ 1