0

I'm working on an Actions on Google chatbot using Dialogflow and Cloud Functions. The runtime is Node.js 6.

Why does this function return the empty string?

function getJSON(url) {
  var json = "";
  var request = https.get(url, function(response) {
    var body = "";
    json = 'response';
    response.on("data", function(chunk) {
      body += chunk;
      json = 'chunk';
    });
    response.on("end", function() {
      if (response.statusCode == 200) {
        try {
          json = 'JSON.parse(body)';
          return json;
        } catch (error) {
          json = 'Error1';
          return json;
        }
      } else {
        json = 'Error2';
        return json;
      }
    });
  });
  return json;
}

This is the intent in which I want to access the json data:

app.intent('test', (conv) => {
conv.user.storage.test = 'no change';
const rp = require("request-promise-native");
var options = {
    uri: 'https://teamtreehouse.com/joshtimonen.json',
    headers: {
        'User-Agent': 'Request-Promise'
    },
    json: true // Automatically parses the JSON string in the response
};

rp(options)
    .then(function (user) {
        conv.user.storage.test = user.name;
    })
    .catch(function (err) {
        conv.user.storage.test = 'fail';
    });
conv.ask(conv.user.storage.test);
});

3 Answers3

0

You can try to use the request module for node.js, I tried my self reproducing your use case and worked fine. The code should be something similar to this:

const request = require('request');

request(url, {json: true}, (err, res, body) => {
  if (err) { res.send(JSON.stringify({ 'fulfillmentText': "Some error"})); }
    console.log(body);
  });

Also, you need to add "request": "2.81.0" in the dependencies section inside your package.json file.

Alex Riquelme
  • 1,475
  • 7
  • 14
0

The function returns the empty string because https sets up a callback function, but the program flow continues to the return statement before the callback is called.

In general, when working with Dialogflow Intent Handlers, you should be returning a Promise instead of using callbacks or events. Look into using request-promise-native instead.

Two clarifying points:

  • You must return the Promise. Otherwise Dialogflow will assume the Handler has completed. If you return the Promise, it will wait for the Promise to finish.
  • Everything you want to send back must be done inside the then() block. This includes setting any response. The then() block runs after the asynchronous operation (the web API call) completes. So this will have the results of the call, and you can return these results in your call to conv.ask().

So it might look something like this:

  return rp(options)
    .then(function (user) {
      conv.add('your name is '+user.name);
    })
    .catch(function (err) {
      conv.add('something went wrong '+err);
    });
Prisoner
  • 49,922
  • 7
  • 53
  • 105
0

You can use Axios as well

To install Axios : npm install axios

OR

You can add it in package.json as a dependency

 "dependencies": {
     "axios": "^0.27.2",
  }

index.js

const axios = require('axios').default;

exports.makeRequest = async (req, res) => {

  axios.get('https://jsonplaceholder.typicode.com/todos/1')// Dummy URL
  .then(function (response) {
    // handle success
  res.status(200).json({
  success:true,
  result:response.data
  })
   
})
  .catch(function (error) {
    // handle error
    
    console.log(error);
  })
};

OR

 const Axios = require("axios");

  exports.makeRequest = async (req, res) => {
  const { data } = await 
  Axios.get('https://jsonplaceholder.typicode.com/todos/1')
    res.status(200).send({data})
 };
Maheshvirus
  • 6,749
  • 2
  • 38
  • 40