Fork me on GitHub
#clojurescript
<
2021-05-10
>
Jakob Durstberger15:05:16

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ójcik16:05:39

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 😄

niwinz18:05:37

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

niwinz18:05:33

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

niwinz18:05:12

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

Karol Wójcik19:05:17

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

❤️ 3
Jakob Durstberger06:05:04

Promesa looks very cool. Might come in handy if things get more complex

Karol Wójcik07:05:32

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

niwinz07:05:42

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

Karol Wójcik07:05:57

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)

niwinz07:05:16

For some reason slack trolled me with formating.

niwinz07:05:13

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

niwinz07:05:27

with the bluebird Promise class

niwinz07:05:17

something like

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

niwinz07:05:48

This will make the bluebird the default one

Karol Wójcik07:05:50

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

niwinz07:05:30

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

Karol Wójcik07:05:50

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.

niwinz07:05:38

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

niwinz07:05:06

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

niwinz07:05:06

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

niwinz07:05:10

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

dpsutton16:05:14

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

dnolen16:05:26

@jakob.durstberger writing directly like that is fine

dnolen16:05:59

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

dnolen16:05:21

because otherwise it starts getting annoying IMO