RegisterHandlers: Yes, we're listening on the Alexa Skills Kit SDK for Node.js
RegisterHandlers
is the function that takes all of our handlers and sets up event listeners for them. In this post, we’ll examine how it does that. 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…
RegisterHandlers
is used in two places in this code. First, it’s used inside the alexaRequestHandler
to define a method called registerHandlers
on our handler
object. This means that we have access to registerHandlers
in our code as well, which you know well as it’s required for the setup of any skill use the JavaScript SDK. This method does nothing more than calls RegisterHandlers
with the handler
object set as the value of this
.
The second place it’s used is also in alexaRequestHandler
, to register the responseHandlers
. We’ll go over these in-depth in a future post, but for now know of them as the :tell
, :ask
, etc. events.
Here’s the code in full. Warning, it’s a long one.
First off, the code is looping through the arguments object. This allows for a non-fixed number of handler objects, useful for when we use CreateStateHandler
to create them. Then it’s setting it to handlerObject
(useful to know so we don’t look at future code and say: “Wait, where’d this come from?”) and making sure it’s an object.
Next up we see that we’re grabbing the event names from the keys of the handlerObject
, because recall that when we create our objects, it’s something like {'AMAZON.YesIntent': function(){}}
.
Then, the code is looping over them one-by-one and checking to see if each is a function. Fair enough—our handlers wouldn’t work otherwise.
Finally, we’re grabbing the event name from the current iteration of the loop and concatenating it with the state that’s defined on the object if that’s present.
Wait, what? We never defined anything resembling {STATE: 'GUESSMODE'}
, right? Well, not directly, but we may have used CreateStateHandler
, which did. We haven’t looked at that portion of the code yet, so spoiler alert:
This comes from CreateStateHandler
and defines a new property with a value of STATE
on our handler objects. By using defineProperty
, it doesn’t come up when looking at all of the keys and it doesn’t need to be skipped over in the loop above.
Here the code is simply creating a new function (localize
) that sends the current arguments to the i18n.t
method with i18n
as the scope. (Recall that i18n
could be overwritten, but is probably always the package i18next
.) Next up we’ll see that we’ll call localize
by a different name.
In this snippet, the context is being set for our handler. There’s fiften different properties to look at, so we’ll do that one-by-one:
on, emit, emitWithState
Alright, I knew I said we’d do this one-by-one, but I don’t want to repeat myself three times and you don’t want me to repeat myself three times. For the on
and emit
methods, the code is binding the current context to these methods. Such is the way of JavaScript: if this wasn’t done, when we called either of these methods, this
would be something else and we could no longer find on
or emit
and, well, it’s just what we’ve gotta do.
emitWithState
is the odd one out here as it’s not binding this
to a method currently on this
but to EmitWithState
. EmitWithState
is a function that will call any registered event with the state concatenated onto the end. Showing us once again that if you name your functions well, they’re fairly self-documenting.
handler
The value of handler is simply this
, which is the handler object that was set up all the way back in alexaRequestHandler
. The upshot here is that we have access to everything on the handler. Indeed, most of what’s happening here is Amazon providing us a gentler way of getting at commonly used resources. Very kind of them.
i18n, locale
Simple: the SDK is providing us with a simpler way of accessing these two. i18n
is, as we looked at earlier, the internationalization module. locale
comes in from the request and can currently be either British English, American English, or German.
t
We just saw the function localize
. This is nothing more than that function, likely named t
to keep consistent with most internationalization libraries, who has this method name as a convention for the translate
functionality.
event, attributes, context, callback, name
Simply _event
, _context
, and _callback
, respectively. We of course still have access to these “private” objects through handler
but there’s no need to use them. attributes
reaches deep into event
, err… well, _event
. name
is eventName
, which by this point has been concatenated with the specified state.
isOverridden
This is a short method, so I’ll just reproduce it here:
This checks to see if there are multiple listeners (listenerCount
comes from EventEmitter
). This should really only be used inside the response handlers (we’ll see later). If your own handlers are overridden, then you’ve got cruft code that you should remove.
response
This is calling ResponseBuilder
, passing it in this
. This function’s a doozy, so we’ll look at ResponseBuilder
in its own post.