Fork me on GitHub
#clojurescript
<
2023-09-23
>
joshmiller02:09:48

I’m having an issue with trying to use setInterval with a function that returns a Promise (via promesa in nbb) where it runs the first time, then runs kind of halfway through on each subsequent call. It looks like from my googling that there is definitely an issue with resolving promises with setInterval in JS. Does anyone have experience dealing with this in CLJS that I can handle idiomatically?

p-himik04:09:57

Can you be more specific? What is the issue?

joshmiller04:09:32

Well, I’m not sure anymore; I moved what I thought was a pure function out of the function that was being called by setInterval and I’m no longer having the problem. I need to figure out how or why that’s the case.

p-himik05:09:05

If a function is truly pure, there's zero reason to call it from setInterval since you can't use its result in any way.

DerTev15:09:55

Hey! Any idea why martian doesnt work as expected? When running (martian/explore @spotify-martian-spec) I just get an empty vector (`[]`) although there should be some routes available. spotify-martian-spec is just (delay (martian-http/bootstrap-openapi "spotify-api-schema.yaml")) where spotify-api-schema.yaml have the same content as https://developer.spotify.com/reference/web-api/open-api-schema.yaml.

DerTev15:09:19

There is also a request to the file and the response seems also right.

p-himik16:09:58

FWIW, works just fine on my end in a fresh REPL with Martian 0.1.25.

stagmoose16:09:59

(defnc YTPlayer [{:keys [video-id]}]
  (let [interval-atom (atom 42)
        on-ready (fn [e]
                   (dispatch [:add-video-ref video-id e])
                   (dispatch [:update-player-curtime video-id (-> e .-target .getCurrentTime)]))
        on-play (fn [e]
                  (reset! interval-atom (js/setInterval (fn []
                                                          (js/console.log "setInterval")
                                                          (dispatch [:update-player-curtime video-id (-> e .-target .getCurrentTime)]))
                                                        1000))
                  (tap> @interval-atom)
                  )
        on-pause (fn [e]
                   (js/console.log "on-pause")
                   (js/console.log @interval-atom)
                   (tap> @interval-atom)
                  ;;  (js/clearInterval @interval-atom)
                  ;;  (reset! interval-atom nil)
                   )
        on-state-change (fn [e] (dispatch [:update-player-curtime video-id (-> e .-target .getCurrentTime)]))]
    ($ YouTube {:videoId video-id #_(:opts #js {:height 200 :width 300})
                :onReady on-ready
                :onStateChange on-state-change
                :onPlay on-play
                :onPause on-pause})))
the on-play function will be called before on-pause , but i found even the atom is set with new value when on-play is called, when on-pause is called, the atom value inside on-pause is still old value. how can i make the function on-pause determine the variable outside its scope (atom in this case) when it is called, not by the init value? (i was using helix with refx, but i think this is a general cljs problem?)

p-himik16:09:57

I'm not familiar with Helix but if it's in any way similar to Reagent in terms of components' state, you're reinitializing the atom on every render. The reason why on-play shows the new value is that you reset the atom before tapping its value.

p-himik16:09:53

The README of Helix makes me think that using atoms here is not a proper way to manage state and that you should be using hooks instead, or at least a class component if you still want to stick to atoms.

p-himik16:09:19

Potentially, maybe you can do it with function components, similar to form-2 components in Reagent.

stagmoose01:09:28

I see the rerendering problem now! Thanks for your hint!

👍 1
stagmoose01:09:17

For future someone, please use use-ref in helix:

(defnc YTPlayer [{:keys [video-id]}]
  (let [interval-ref (hooks/use-ref nil)
        on-ready (fn [e]
                   (dispatch [:add-video-ref video-id e])
                   (dispatch [:update-player-curtime video-id (-> e .-target .getCurrentTime)]))
        on-play (fn [e]
                  (reset! interval-ref (js/setInterval (fn []
                                                         (js/console.log "setInterval")
                                                         (dispatch [:update-player-curtime video-id (-> e .-target .getCurrentTime)]))
                                                       1000)))
        on-pause (fn []
                   (js/clearInterval @interval-ref)
                   (reset! interval-ref nil))
        on-state-change (fn [e] (dispatch [:update-player-curtime video-id (-> e .-target .getCurrentTime)]))]
    ($ YouTube {:videoId video-id #_(:opts #js {:height 200 :width 300})
                :onReady on-ready
                :onStateChange on-state-change
                :onPlay on-play
                :onPause on-pause})))

stagmoose01:09:47

i think this is really neat!