Fork me on GitHub
#re-frame
<
2018-11-17
>
heyarne10:11:28

hey there. i've got an audio player in my app and playing audio is handled by a couple of effects that i've registered in re-frame. they look like this:

(re-frame/reg-fx
 :audio/play
 (fn [stream-url]
   (when-not @audio
     (reset! audio (js/Audio.))
     (attach-listeners! @audio))
   (.pause @audio)
   (set! (.-src @audio) stream-url)
   (.play @audio)))
while this works on chrome and ff i'm running into problems in safari, which gives me and unhandled promise rejection as soon as (.play @audio) is called. the reason for this seems to be this: https://www.reddit.com/r/webdev/comments/71nkym/safari_11_has_a_major_change_to_web_audio_api/

heyarne10:11:25

does anybody have any idea how one would deal with this? the thread mentions AudioBuffers but tbh this seems like it's not quite futureproof, considering the intent of disabling autoplay in the first place

heyarne10:11:36

i've tried initializing the audio elemen non-lazily which didn't make any difference. it's not quite clear to me how safari figures out the "on user interaction" part

abdullahibra12:11:15

how can i call dispatcher withing another dispatchers ?

abdullahibra12:11:19

i'm in situation which need to add-item "dispatcher#1" and after i add the item i need to go to it's page "dispatcher#2"

Lu14:11:45

If you are registering your first event as a reg-event-fx, you can return a map with a key :dispatch [your event name] .. and if you need to dispatch more than one event you can use :dispatch-n [[event one] [event two]]

Lu14:11:23

@abdullahibra

(re-frame/reg-event-fx 
  :my-event
  (fn [{:keys [db]} [ _ arg1]]
   {:db (do something with it)
    :dispatch [your second event]
   }))

abdullahibra16:11:02

@lucio great thanks 🙂

🐛 4
perrygeo21:11:18

speaking of dispatch-n, I've got a newbie question for everyone

perrygeo21:11:30

I'm working on visualizing a 2D geometry simulation in re-frame. I've got the basic single-step logic working,

(re-frame/reg-event-db
 ::next-step
 ...)
Dispatched from a button, I can advance the simulation one click at time.

perrygeo21:11:22

What I'm looking to build now is a "Play" button that would automatically advance the simulation to the end. My naive first approach was to call dispatch-n on a lazy sequence of ::next-step events.

(re-frame/reg-event-fx
  ::play-all-steps
  (fn [cofx _]
    (let [rest-of-simulation (take 49 (repeat [::next-step]))]
      {:dispatch-n rest-of-simulation})))
This sort of worked in that the simulation was executed (logs confirm this). But handling the dispatch-n effect completely blocks the animation frame. I only get the final result rendered.

perrygeo21:11:50

Is there a way to dispatch a chain of n events such that the animation frame is processed on each event? Like a dispatch-n-async or something?

perrygeo21:11:43

Alternatively, am I missing an obvious, more idomatic re-frame pattern for accomplishing this?

manutter5121:11:30

I would have a counter var somewhere in app-db, and a :play-next-step handler that would decrement the count and, if greater than zero, do the next step and fire another :play-next-step event.

perrygeo22:11:07

of course! for some reason I was avoiding recursive event calls but that works pretty well

perrygeo22:11:20

oh, hmm. it "works" in the same sense as the dispatch-n version - it runs but blocks the animation frame.

4
manutter5122:11:21

(follow the link for the docs on how to use :dispatch-later)

🤯 4
genekim03:11:48

:dispatch-later!!! Wow! (How many times have I used core.async to sleep for 100ms and then dispatch an event! Thank you!)

👍 4
perrygeo22:11:11

Yes! adding a 50 ms delay works

perrygeo22:11:05

Thanks for your help on this @manutter51 - I'm still not convinced that this is a good idea from a performance standpoint (running the simulation and the animation in the same browser thread 😬 ) but it's working well enough!

perrygeo22:11:32

fwiw the final handler looks something like

(re-frame/reg-event-fx
 ::play-next-step
 (fn [cofx _]
   (let [...]
     {:db (assoc current-db
                 :geom new-geom
                 :step (+ 1 step))
      :dispatch-later [{:ms 5 
                        :dispatch [(if (< step max-step)
                                    ::play-next-step
                                    ::reset)]}]})))

genekim03:11:48

:dispatch-later!!! Wow! (How many times have I used core.async to sleep for 100ms and then dispatch an event! Thank you!)

👍 4