react/redux to elm feature comparison: playing morse sounds
This post is about how the feature of listening to morse sounds when pressing the button…
…is implemented.
react/redux
Let’s start with the user interaction in the UI:
playSound
is an action that is surfaced through react-redux’ connect
-functionality. The action looks like that:
This type of function is supported by the redux-thunk middleware, which provides the dispatch and getState functions to be able to perform side-effects within a user-UI interaction. Digging deeper:
The async/await, part of ES2017, but already available through babeljs-transpiling, allows you to work with promises much like you do with Tasks in the post .NET 4.5 world. This makes the code that performs the necessary time delays much easier to read.
Finally startSound
and stopSound
connect and disconnect the oscillator that is set up to the audio output of the browser.
elm
As you can imagine, not every single browser API is surfaced to elm - hence the concept of defining ports, a subsystem that allows you to interop to plain javascript and its access to all of the browser’s API. Therefore, we go ahead and define ports to start and stop the sound:
In javascript, we need to fill these ports with life:
Now that we have this in place, we can stay in elm to implement the functionality. Let’s start in the UI again:
OnListenToMorse
is a defined message that needs to be handled in the update
function of your application.
Just like in the redux app, where I didn’t show any reducer code, implying that nothing changes in the application’s model, the only reaction here consists of initiating a side-effect.
What happens in playWords
?
In other words, first the user input is converted to a list of morse symbols.
This is then processed to a list of list of tuples that state at
which relative time in milliseconds which message should be piped into the update function (See e.g. Dot -> playDot + applying speed factor
).
The final ingredient to this magic is the sequence function from the elm package delay. The code is actually not super-complex,
it does the necessary plumbing to call out to Process.sleep the elm equivalent to javascript’s setTimeout
.
What happens then, when the SoundMsg StartSound
and StopSound
messages are received?
And here is where you finally find the calls to the interop ports we defined to connect and disconnect the Oscillator :)
Which route do you prefer?