0

I'm trying to build a backend webhook for the Google Assistant that reads records from DynamoDB.

This is my code:

// Handle the Dialogflow intent named 'trip name'.
// The intent collects a parameter named 'tripName'.
app.intent('trip name', (conv, {tripName}) => {

    const dynamoDb = IS_OFFLINE === true ?
        new AWS.DynamoDB.DocumentClient({
            region: 'ap-south-1',
            // endpoint: 'http://127.0.0.1:8080',
        }) :
        new AWS.DynamoDB.DocumentClient({
            region: 'ap-south-1',
            // endpoint: 'http://127.0.0.1:8080',
        });


        const params = {
            TableName: ACTIVITIES_TABLE
            Key: {
                'name':tripName
            }
        };

        // conv.close('error retrieving!'); THIS WORKS
        dynamoDb.get(params, (error, result) => {
            // conv.close('error retrieving!'); THIS DOES NOT

            if (error) {
                conv.close('error retrieving!');
            }
            else {
                conv.close(JSON.stringify(result, null, 2));
            }
        });
});

If I were to use conv from outside the DynamoDB function it works, but from inside it does not and return this error:

2019-08-03T03:56:22.521Z ** ERROR Error: No response has been set. Is this being used in an async call that was not returned as a promise to the intent handler?

It made me conclude that maybe I'm not allowed to access an arrow function argument from another nested arrow function?

I'm using Actions on Google Client Library.

Seif
  • 701
  • 4
  • 13
  • 32
  • 2
    You're allowed to do that, but not with the framework you're using. – Jack Bashford Aug 03 '19 at 04:45
  • I updated the question about what library I'm using. @JackBashford – Seif Aug 03 '19 at 04:51
  • Can you add `conv` as an argument to the nested function? `dynamoDb.get(params, (error, result, conv) => {...` – Nathan Fries Aug 03 '19 at 05:58
  • 2
    Possible duplicate of [Error: No response has been set. Cloud Functions for Actions on Google Assistant](https://stackoverflow.com/questions/49909455/error-no-response-has-been-set-cloud-functions-for-actions-on-google-assistant) – Molda Aug 03 '19 at 06:00
  • 3
    If you do some **async calls** like quering DB you need to **return a promise**. – Molda Aug 03 '19 at 06:01

1 Answers1

2

The problem has nothing to do with accessing parameters from one arrow function in another - that is perfectly allowed.

The issue is, as the error message suggests, that you are using an asynchronous function (a function that requires a callback0, but not returning a Promise object. The actions-on-google library requires you to return a Promise from your Intent Handler if you're doing any asynchronous operations so it knows to wait for those operations to complete.

You'll need to switch from using a callback in your call to dynamoDb.get() to using a Promise instead. To do this, you need to not include the callback function, so get() returns an AWS.Request object. This object has a promise() method, so you would use this to return the results from the Promise and then() chain. (And you must return this Promise.)

In your case, it might look something like this

    return dynamoDb.get(params).promise()
      .then( result => {
        conv.close(JSON.stringify(result, null, 2));
      })
      .catch( error => {
        conv.close('error retrieving!');
      });
Prisoner
  • 49,922
  • 7
  • 53
  • 105