alexa-js / alexa-app

A framework for Alexa (Amazon Echo) apps using Node.js
https://www.youtube.com/watch?v=pzM4jv7k7Rg
MIT License
1.03k stars 212 forks source link

Async call in intent event handler? #340

Closed roschler closed 6 years ago

roschler commented 6 years ago

I am trying to query an external server in my intent handler using alexa-app. I am using a Bluebird promise inside my intent handler to make an asynchronous call to my external dialog server:

alexa_app_lib.intent("search_query", {
        // Set up a slot for the received input.
        "slots": {
            "user_input": "AMAZON.SearchQuery"
        },
        // Suggest sample input the user might say to Alexa.
        "utterances": [
            "the {user_input}"
        ]
    },
    function(request, response) {
        if (g_NoDialogServer)
        {
            // Just return a simple response without querying the dialog server (for testing/debugging)  THIS WORKS FINE.
            response.say("Tell me request received.");
            response.shouldEndSession(false);
        }
        else
        {
                            // THIS RETURNS NOTHING TO ALEXA SKILL SIMULATOR.
            let userId = extractUserIdFromAlexaPostRequest(request);

            // Query our ChatScript dialog server.
            chatscript_support.queryTheChatServer_promise(userId, "user input", null, null, null)
                .then(function(chatScriptResponseObj)
                {
                    // Respond to the user with the response given to use by the dialog server.
                    response.say(chatScriptResponseObj.text_to_say);

                    // Follow the dialog server's suggestion to end the session or not, if
                    //  that value is present.
                    let bEndSession = common_routines.isExplicitlyTrue(chatScriptResponseObj.is_session_ended);
                    response.shouldEndSession(bEndSession);
                    return;
                })
                .catch(function(err)
                    commonInTellMeEventErrorHandler(response, "An unexpected error was caught and handled.", null);
                    return;
                });
        }
    }
);

Unfortunately no response is generated. My alexa-app postRequest never triggers like it usually does, and the Alexa Skill simulator hangs waiting for a response. This doesn't happen when I don't make the async call and immediately make a call to response.say() with some arbitrary text. That works fine and I see the result in the Alexa Skill simulator.

I'm guessing that the problem is with having the intent handler return without calling response.say() before the intent handler exits? In other words, although my Promise that calls the external server does fire properly and calls response.say() later in the Promise "then" block, it's too late because the intent handler code has already returned? Note, I'm sure that the Promise works properly because I have traced out the code and seen the response.say() call being made properly in the Promise "then" block.

If so, how do I call an external server to process the user input from within an alexa-app intent handler? I'm really hoping I don't have to try and do something like figuring out how to make a blocking call from a Node.JS code block.

roschler commented 6 years ago

Sorry. I think this tells me what to do in that I need to return a promise myself rather than executing directly:

https://www.npmjs.com/package/alexa-app#asynchronous-handlers-example

I'll try that now.