Check out a free preview of the full State Machines in JavaScript with XState course:
The "Interpreting Machines & Creating a Service" Lesson is part of the full, State Machines in JavaScript with XState course featured in this preview video. Here's what you'd learn in this lesson:

David refactors the code created in the previous sections, builds a service, and explains that a service is a run instance of a state machine. If a state machine is a blueprint, a service is one instance of the blueprint.

Get Unlimited Access Now

Transcript from the "Interpreting Machines & Creating a Service" Lesson

[00:00:00]
>> Transitioning we saw, we give it the current state, and we give it the event. Now the event, again, can be either a string, or it could be that event object. So if the event doesn't have any payload, we could just pass in CLICK_GOOD. And then that should work.

[00:00:21] So it does take us to thanks, which is the value over here. Perfect, everything is working. All right, but keeping track of the state like we saw, it's hard. It's a little bit fragile because now you have this floating mutable value, and you're not really even cleaning up that service that's keeping track of the state all the time.

[00:00:49] So, that's why Xstate provides an interpret function. And this interpret function creates what's called a service. So, in Xstate lingo, a service is a running instance of a machine. You could consider the machine like a blueprint for how your logic is supposed to look. And the service is just a single instance of that machine.

[00:01:11] So when you create a machine, this is essentially a stateless pure object, it doesn't do anything. It doesn't hold any current state. That's what the service does. And so that's why you could pass this machine back and forth between many things. It is not a mutable object. It's just a blueprint.

[00:01:33] It's a very, very fancy JSON object. So, this service is gonna be what we want. In order to create a service, you pass in the machine to interpret. And then you you could listen to state changes on that service by registering a state listener in the onTransition method.

[00:01:56] And so whenever you get a new state, including the first state, you could do whatever you want with it. So in this case we're just logging it to the console. And then you have to start a service. Services don't start immediately, and that's good because you don't want anything unexpected to happen like weird timing issues.

[00:02:13] You want to be able to control exactly the moments that the service Is actually up and running. So instead of doing all of this, let's actually put this in the service. So I'm just going to say const feedbackService = interpret. And we're going to import this from Xstate, up above over here.

[00:02:36] Now, interpret takes one to two arguments. The only argument that we're gonna worry about right now is the first one, which is that machine. So we pass it the feedback machine, which again is a blueprint for how that service is going to behave. Let's add an event listener as well, so we could say feedbackService.onTransition.

[00:02:59] And we get the state. So let's just console.log(state.value). Remember that the state.value is the current finite state value of that state object. And then we start the service. So you can see immediately we get the question state and that's because it's going to give us the the first state immediately.

[00:03:29] And if you start listening later, it will give you the latest state. So remember, a service is a live instance. It's keeping its internal state and it's internally mutating it. So it's going to give you whatever it's instance of a status. You could also think of this sort of like a singleton.

[00:03:47] All right, so now let's actually get some things to happen over here. I'm gonna say, window.send = feedbackService.send. And we're doing this because we want to send events to the feedback service. So let's say we send: 'CLICK_GOOD'. All right, cool. You'll see that it transitions to thanks. And actually, we do have the, All right, so yeah, so we have feedbackService.send.

[00:04:23] So you could just do feedbackService.send, which is just like your send function that you made in the previous exercise. And you could send any sort of event object to it. So in this case, we're gonna send type:'CLICK_GOOD'. And so that, again, is going to log things. Now when you're not using a service anymore, for example, if this service represents something that you only wants to exist for a moment in time, and then you're done using the service.

[00:04:53] It's smart to call service.stop. What this is going to do, is it's going to dispose of all the listeners registered to the service, as well as any ongoing activities or actions or invoked services. Or anything else that we're gonna cover later in this workshop. So, it's smart to call service.stop to clean up everything when you're no longer using it.