1

I am developing a Dialogflow webhook using dialogflow-fulfillment-nodejs client to find temperature for a city. While using the services to fetch the temperature for a city, everything works and the correct response is also generated but the response is not sent to the user even when the right method is called.

Here is the issue in the Dialogflow GitHub repo

Code

function getTemp(agent) {
    const timeStart = new Date().getTime();
    console.info(`temp function called`);
    // agent.add(`Temperature in New Delhi is 50 degree Celsius!`); // This works
    serviceRequest.getTemp("New Delhi", function(resp){
        if (resp['status'] === 'Y') {
            // success
            const msg = `Temperature in New Delhi is ${resp['temp']} Celsius!`;
            console.log(`Speech Response -- ${msg}`);
            console.log(`Type of msg -> ${typeof msg}`);
            agent.add(msg);
        } else {
            // failure
            agent.add(`There was some error with the backend. Please try again later.`);
        }
        const timeEnds = new Date().getTime();
        console.log("\nComplete 'getTemp' process took " + (timeEnds - timeStart) + " milliseconds.")
    });
    console.log("------ temperature function ends here ------");
}



'getTemp': function (city, callback) {
        let respBack = {};
        doTimeOutTest(function(resp){
            respBack['temp'] = resp;
            respBack['status'] = 'Y';
            callback(respBack);
        });

    }


function doTimeOutTest(callback){
    // below commented code takes < 10 ms to execute, but does not send any response back to dialogflow as call ends before it is executed
    // setTimeout(function() {
    //     callback("30 degree");
    // }, 1);

    // Below code works even when it takes more time to execute
    for(let i=0; i<10000; i++){
        for(let j=0; j<10000; j++){
            //
        }
    }
    callback("30 degree");
}

Console Logs

When the commented code runs

>>>>>>> S E R V E R   H I T <<<<<<<

temp function called
------ temperature function ends here ------
Speech Response -- Temperature in New Delhi is 30 degree Celsius!
Type of msg -> string

Complete 'getTemp' process took 10 milliseconds.


When the uncommented code runs

>>>>>>> S E R V E R   H I T <<<<<<<

temp function called
Speech Response -- Temperature in New Delhi is 30 degree Celsius!
Type of msg -> string

Complete 'getTemp' process took 77 milliseconds.
------ temperature function ends here ------

NodeJS Dialogflow src code link - https://github.com/dialogflow/dialogflow-fulfillment-nodejs/blob/master/src/dialogflow-fulfillment.js

Abhinav Tyagi
  • 5,158
  • 3
  • 30
  • 60
  • The problem likely lies in the code you’ve omitted from this question. – Robert Levy Jul 07 '18 at 04:32
  • I have added the complete code for the function and log trace – Abhinav Tyagi Jul 07 '18 at 04:53
  • Interesting... if you look at the code for the dialogflow fulfillment package you can see where they use instanceOf but it’s got the right side as things it defines or imports rather that user parameters. My best guess would be to nuke your node_modules directory and do a fresh npm install – Robert Levy Jul 07 '18 at 11:49
  • Deleted the Node Module of the project and reinstall using sudo npm install. Still the same error :( – Abhinav Tyagi Jul 07 '18 at 12:34
  • Their documentation says to use version ^1.0.0 but no version found above ^0.4.1 which I am using !! – Abhinav Tyagi Jul 07 '18 at 13:02
  • Now both the codes are not working... the code that was working a few days back is also giving the same error... following code was working fine https://github.com/abhi007tyagi/dialogflow-fulfillment-nodejs/blob/9f67a3ffebda167be3bdb93c7ca12776aa891049/samples/express-js-integration/server.js – Abhinav Tyagi Jul 07 '18 at 15:02

2 Answers2

3

You need to return a promise in your handler function. function handlers support promises now so you can return a promise and process things like http requests in the promise. Here is an example of using the request library:

function dialogflowHanlderWithRequest(agent) {
  return new Promise((resolve, reject) => {
    request.get(options, (error, response, body) => {
      JSON.parse(body)
      // processing code
      agent.add(...)
      resolve();
    });
  });
};

You can also move the HTTP call to another function that returns a promise. Here is an example with the axios library:

function dialogflowHandlerWithAxios(agent) {
  return callApi('www.google.com').then(response => {
    agent.add('My response');
  }).catch (error => {
    // do something
  })
};

function callApi(url) {
    return axios.get(url);
}
mattcarrollcode
  • 3,429
  • 16
  • 16
  • 1
    Thanks so much Matt :) I will use the first approach. Also, I found out that doing a synchronous call, using Sync-Request (https://www.npmjs.com/package/sync-request), also solves the issue. – Abhinav Tyagi Jul 10 '18 at 04:47
  • Great! Glad I could help. Please note that the sync-request package is not appropriate for production use and could impact performance. The preferred solution is to a return a promise in your intent handler. – mattcarrollcode Jul 10 '18 at 18:49
  • 1
    Yes Matt. I am returning a promise only. – Abhinav Tyagi Jul 11 '18 at 00:41
0

An example using then-request:

const thenRequest = require('then-request');

function callApi(resolve){

    var req = thenRequest('POST', 'https://api_url_here...',{
      headers: 
       { 
        '.....': '....'
       }
    });

    req.done(function (res) {
        ....
        agent.add("Some text goes here...");
        ...
        resolve();
    });     
}

Fire the request:

return new Promise((resolve, reject) => { 
    callApi(resolve); 
});
Dionis Beqiraj
  • 737
  • 1
  • 8
  • 31