Refactor the app.js file


#1

Hello all,

I have a question about the app.js file in Jovo proyect. In this file I have all the intents and all the functions and I want to ask If I can separate all the code in this file in others files and in this way get a structure and a much more readable code.

Thank you very much in advance.

Greetings,

Alberto.


#2

I try to structure my voice app in a way such that all intents have a separate file e.g. launchintent.js, welcomintent.js where each file contains an exported handler. These files are then imported and used in the app.setHandler() method in app.js.

I am using typescript btw and I donā€™t know if this is the best way to do it, but it provides quite a nice structure to the code.


#3

Hi Michael,

Thanks for your answer!

I donā€™t understand this:

each file contains an exported handler.

How do you import a file with the intent in the app.js?

Regards!


#4

This should help:


#5

Hi Jan!

Thank you for the tutorial but I have a doubt.

Āæstates is a new folder in the proyect at the same level as src, db, test, etc?

I have followed the tutorial and I have the following error:

Message: Cannot find module './states/Intent.js'

Regards.


#6

It would need to be a folder inside src


#7

I have the following code:

const INTENT_1_STATE = require(ā€™./states/Intent1.jsā€™);
const INTENT_2_STATE = require(ā€™./states/Intent2.jsā€™);
app.setHandler({
LAUNCH() {

    this.toStateIntent('INTENT_1_STATE', 'Intent1');
    this.toStateIntent('INTENT_2_STATE', 'Intent2');

},
INTENT_1_STATE,
INTENT_2_STATE,

But It doesnā€™t work. I want to launch the intents that have your file in the states folder.

Thank you in advance.


#8

How does your ./states/Intent1.jsā€™, for example?


#9

module.exports = {
Intent1() {
if (isNotEmpty(this.$inputs.actuador) && this.$inputs.actuador.value !== ā€˜ā€™) {
YesOrNo.call(this, this.$inputs.actuador.value);
}
},
}

isNotEmpty() and YesOrNo() are functions found in the file > ./states/Intent1.jsā€™


#10

Seems like you havenā€™t added a state. This is why this.toStateIntent('INTENT_1_STATE', 'Intent1'); wouldnā€™t work


#11

I have followed the tutorial like this:

The problem is to launch the two intents. If I launch only one intent, it works correctly, but if I launch the two intents in the app.setHandler() like this:

app.setHandler({
LAUNCH() {
this.toStateIntent(ā€˜INTENT_1_STATEā€™, ā€˜Intent1ā€™);
this.toStateIntent(ā€˜INTENT_2_STATEā€™, ā€˜Intent2ā€™);
},
INTENT_1_STATE,
INTENT_2_STATE,

The program doesnā€™t work.


#12

Intent redirects shouldnā€™t be done like this, rather like this with a return statement:

LAUNCH() {
    return this.toStateIntent(ā€˜INTENT_1_STATEā€™, ā€˜Intent1ā€™);
},

There shouldnā€™t be another redirect happening. Each interaction (request) should only have one response


#13

But then, in app.setHandler, can I only run one Intent? I couldnā€™t run Intent2 as well?


#14

Could you explain the goal of this a little more? Typically, you wouldnā€™t run two intents in parallel, because you would only create one response per request.

More here:


#15

Of course Jan, sorry if Iā€™m not explaining myself well.

Imagine that Intent1 is used to make a hotel reservation and Intent2 to confirm if you want to do anything else after the reservation.

Then, when we launch the application, the user says:
ā€œI want to make a reservation tomorrowā€ and the assistant answers: ā€œOkay. Do you need anything else?ā€ (Intent1).

The user answers: ā€œNothing else, thank youā€ and the assistant answers: ā€œHave a good day!ā€ (Intent2).

For that reason, I need both Intents to be executed because if I do that execution I get the following error:

Code:
ERR_NO_ROUTE
Message:
Could not find the route ā€œINTENT_2_STATEā€ in your handler function.

if I can only execute one intent like this:

LAUNCH() {
return this.toStateIntent(ā€˜INTENT_1_STATEā€™, ā€˜Intent1ā€™);
},

I will have the error. That is why I had introduced the two intents in the app.setHandler().
If I have all the intents in the app.js file it doesnā€™t give me any error, but I wanted to refactor the code so that the app.js file wouldnā€™t be so big and so unreadable.

I hope you can understand me.

Regards.


#16

Have you read through the requests and responses docs? Also, I think before diving too deep into separating handlers into files, it would be great to get some more understanding of how voice interactions work in Jovo. The best way to understand how it works is to follow our Adventure Game tutorial (which has a similar concept, as itā€™s asking the user for input):

https://www.jovo.tech/courses/project-2-adventure-game


#17

I think you still donā€™t understand meā€¦ :pensive:

That was an example.

I did that tutorial and I understand it. I have my application working properly. The only thing I wanted is that instead of having all the intents in the same file, I could separate each intent in each file and call them from app.js when necessary as said @michaelwapp , but I see that I canā€™t do it so Iā€™ll have to leave all the intents in the app.js file even if itā€™s a file with many lines of code and difficult to read.


#18

@alberto I answered your dm, but if anyone else is interested, here is how I structure my voice app.

src/
   states/
      launchtintent.ts
      welcomeintent.ts
   app.ts

Where one intent e.g. launchintent.ts looks like this:

import {Handler, Log} from 'jovo-core';

export const launchintent: Handler = {
    LAUNCH() {
        Log.info('Started LaunchIntent');
        return this.toIntent('WelcomeIntent');
    }
};

and the app.ts looks like this:

// ------------------------------------------------------------------
// APP INITIALIZATION
// ------------------------------------------------------------------
import {App} from 'jovo-framework';
import {Alexa} from 'jovo-platform-alexa';
import {GoogleAssistant} from 'jovo-platform-googleassistant';
import {JovoDebugger} from 'jovo-plugin-debugger';
import {FileDb} from "jovo-db-filedb";
// ----
// STATE IMPORTS
// ----
import {launchintent} from "./states/launchtintent";
import {welcomeintent} from "./states/welcomeintent";
// ------------------------------------------------------------------
// STATES
// ------------------------------------------------------------------

const app = new App();

app.use(
    new Alexa(),
    new GoogleAssistant(),
    new JovoDebugger(),
     new FileDb(),
);

// ------------------------------------------------------------------
// APP LOGIC
// ------------------------------------------------------------------

app.setHandler(
   launchtintent,
   welcomeintent
);

export {app};

#19

Hi, how can i pass parameters beween states?


#20

you can do it with this.$data.someKey = someValue;

more here: