EmitWithState: the final piece of alexa.js for the Node.JS Alexa Skills Kit SDK
In this post we’re going to look at the final parts of
alexa.js, focusing on
EmitWithState, but also looking at how exceptions are caught if they aren’t elsewhere, how state handlers are created, and what is exported.
As a reminder, this is the Dig Deep series, where we look line-by-line at the tools and libraries we use to build voice-first experiences. This is not the place to go for tutorials, but if you want to learn interesting little nuggets about what you use every day, off we go…
The first thing we’ll look at is the
createStateHandler function. The name is a bit misleading, as it doesn’t in fact create a handler. It is, however, exported as
CreateStateHandler and we use it to attach a state to our handlers.
What it does is it takes an object (which should contain our handlers for a given state) and defines a property on it. That property is the
'STATE'), with a value of either the provided state or an empty string. It’s important to note that it is using
defineProperty and not just adding a new key/value pair. This is as new properties are not enumerable in a
for...in loop. Because of this,
RegisterHandlers does not need to check for and skip anything with a key of
For what it’s worth, this code feels overly cautious. I’m hard-pressed to think of a situation where you would call this function without providing an object (so no need to assign
obj to an empty one) and even harder pressed to think of a situation where you would call it without passing a
state value in. I could be wrong, so tweet at me if that’s the case.
Unlike our previous,
EmitWithState does exaclty what it says it will: emit with the state. This function does what I would expect:
throw if there are no arguments provided.
EmitWithState was bound to our
handler object, so when we see after the conditional that we are getting the
state from the current context, that’s what is happening. In other words, we’ve set the state inside our code. This code is taking the function (this can be, but doesn’t have to be an intent) and prepending it to the current state. For example, we could wish to trigger the
getScore function with a mid-game state (let’s say it’s represented by the string
_MIDGAME). In this case, what will be emitted will be
In the next conditional, it’s seeing if there are any registered listeners with the newly-formed string. If not, then this is clearly an unhandled intent (no handlers === unhandled). So instead of looking for that intent, we want to see if there’s an unhandled handler on the current state. If there’s none of that, then an error is thrown.
Finally, if it gets through all of that, the event string (either the intent plus state or `Unhandled` plus state) is emitted with all of the arguments, allowing us to pass arguments to—again—either the intent handlers or any other function.
This is simple: if there’s an uncaught exception, we log out the stack trace and throw the error. Useful for logging (e.g. in CloudWatch).
Finally, the exportation of three things:
LambdaHandler), which is renamed just
handler by the time it’s available to us
CreateStateHandle), which is available to us as
StateString, which is also available to us with that name
That’s it for
alexa.js! It’s been a long part of the series, next up we’ll look at