Check out a free preview of the full Introduction to Elm, v2 course

The "Subscriptions" Lesson is part of the full, Introduction to Elm, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Richard shows how subscriptions fit into the Elm Architecture, giving the example of Browser.onMouseMove.


Transcript from the "Subscriptions" Lesson

>> Richard Feldman: In an Elm course, what could possibly be the final frontier, but talking to JavaScript. So we're gonna talk about a few concepts here. Subscriptions, guarantees, sending data to JavaScript and receiving data from JavaScript. So let's start by talking about subscriptions and in particular in the context of responding to custom events.

So here's something that it is part of Elm's HTML API. It's this function called on. And this is sort of the general most flexible version of on click, on input, on whatever you want. It takes a string. So for example, on "mousemove". Then it takes the Decoder, and the purpose of this Decoder is not to decode JSON, but rather to decode an event object from JavaScript.

So as it turns out, because JSON is the JavaScript object notation. When you want to deal with a JavaScript object and describe how to traverse it and pull values out of it, you can use the same exact JSON decoder API that you used for actual JSON. So this is gonna say, given a JavaScript event object from this particular event type, how can I translate the fields in that object, the data inside that object into some useful Elm value?

So you give it on, you give it a string, a Decoder of whatever this message you want to be is going to be. And then finally, it will give you back an HTML attribute that responds to that particular message. So as an example, I might say, I'm gonna make a div.

I'm gonna say, on "mousemove" and then I'm gonna give a custom mousePointDecoder, which is going to look into the event object and get the x, y coordinates of the mouse. And maybe I'll display them on the screen. Maybe I'll use them for some animation, who knows? Could use it for any purpose I want, but this thing is a very flexible way to do that.

This is a nice API for that. Okay, so we could use a similar kind of concept to respond to Window Events that don't actually correspond to any particular element in the DOM, but rather just to the entire browser window. And to do that, we can't quite use this.

Because this only works for values that were putting into the DOM. This attribute is plenty useful if we've got a div that we wanna stick it on, but we can't just take an attribute and just put it on the window that doesn't work. The Window doesn't have attributes.

So here's what we do instead. There's a function called Browser.onMouseMove. And it has the same idea of give me a Decoder and that will describe how to deal with this event object that it's gonna get every time the user moves the mouse anywhere in the window. But it gives back this new value that we haven't seen before called a sub which is short for a subscription.

>> Richard Feldman: So here is how subscriptions fit into our view of the Elm architecture. So we started out with model, view and update. We introduced commands to that and the commands are something that update returns. Subscriptions are the final piece of the puzzle. This is the last piece of the, sort of Elm architecture that exists.

And much like commands, subscriptions is essentially one more way for messages to get sent from the runtime to update. So we can now notice this sort of pattern where essentially update is the brains of the Elm application and it receives messages from a few different sources. One is from view, so in response to user events.

Another is from commands that update itself sent off, whether they be randomness or HTTP requests. And then finally, we have subscriptions. Now fundamentally, subscriptions are essentially event listeners that are global. So whereas view will respond to user inputs for things that happen in response to actions on the DOM, subscriptions can be things like user inputs in the global context which is to say like a global mouse move, but they can also be other things.

They can be things like I want you to just send a message to update every three seconds, for example. You can say it is sort of based on a timer. You can also use this to subscribe to WebSockets and say, every time the server sends me something, regardless of what's going on, I want you to send this message to update.

And again, fundamentally, this is going to be sending message to update and that's the way that things are going to happen in this world of subscriptions. There's nothing else that they do other than specify things that result in messages getting sent to update. The way that we specify with subscriptions we care about is there's a function that we pass to our program that's called, usually subscriptions in the same way that have update and view.

But again, it could be named whatever we want it, it just needs to sort of fit the bill in terms of the types. And the purpose of that function is it takes a model and then returns any subscriptions that we care about based on that model. So you can sort of turn subscriptions on and off.

You could say, for example, right now, I care about mouse moves. And every time the user moves the mouse, I wanna send a message to update. You might also later say, actually know what? Based on the current state of the model, we don't care about that one anymore.

We're gonna say, sub.none just like command.none and you know what? Right now, we're just not doing any of those. So that prevents us from sort of flooding update with all of these spurious messages for things that we don't care about. It's a way to say, yeah, every time the model changes, not only is the runtime gonna call a view to say give me a new description of how I want the page to look, but also it's gonna take that new model and pass it subscriptions.

And say, hey, is there anything you want to subscribe to or not subscribe to anymore based on how the application state has changed? In practice, it's pretty common to have subscriptions return the same thing, no matter what every time. You'll just say, we always care about this, or we never care about this.

But that flexibility is there if you wanna have things that are toggled on and off based on circumstance.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now