-1

I'm trying to call a REST service from aws lambda function but the execution isn't triggering code inside callback function. The REST service is working fine on standalone node.js server.

In the CourseInfoIntent, I'm fetching the slot value and forming a endpoint url. I have created https_options_get with required values.

exports.handler = function(event, context, callback){
  console.log("Course Info Skill Started");
  var alexa = Alexa.handler(event, context);
  alexa.APP_ID = APP_ID;
  alexa.registerHandlers(handlers);
  alexa.execute();
};

const handlers = {
  'LaunchRequest': function(){
    console.log("Inside Launch Request");
    this.emit('CourseInfoIntent');
  },
  'CourseInfoIntent': function(){
    // fetch the lesson id from data as per slot_type(Lesson) value
    console.log("Course Info Intent Started");
    //this.event.request.intent.slots.slotname.value for retrieving slot value from utterance
    var req_lesson = this.event.request.intent.slots.Lesson.value;
    console.log("Lesson Requested: " + req_lesson);
    var lessonId = data[req_lesson];
    console.log("Lesson ID: " + lessonId);
    path = path + '?LessonID='+lessonId;
    var url = "https://" + hostName + path;
    console.log("Rest url is :-> " + url);

    // create opyions for https request
    var https_options_get = {
      host: hostName,
      method: 'GET',
      path: path,
      headers: {
        'Content-Type': 'application/json'
      }
    };

    var result = getJson(https_options_get, function(err){
      console.log("Inside callback function");
      const speechOutput = "There has been an error with your request" + err;
      this.response.speak(speechOutput);
      this.emit(':responseReady');
    });
    const speechOutput = "The name of the lesson is " + result;
    const reprompt = "Do you like to know about more sessions? Answer Yes or No";
    this.response.speak(speechOutput).listen(reprompt);
    this.emit(':responseReady');
  }

getJson function is used to make a REST call using node.js https module. But on checking logs in cloudwatch I only get to see the log till "Inside new getJson function:" log message after the function call var request = https.request(https_options_get, function (response) {} does not trigger.

function getJson(https_options_get, context, callback) {
  console.log("Inside new getJson function: ");
  var request = https.request(https_options_get, function (response) {
      console.log('In GET Request Function block');
      var body = '';
      response.on('data', function (chunk) {
          body += chunk;
      });
      response.on('end', function () {
          var bodyJSON = JSON.parse(body);
          console.log('bodyJSON:-> ' + bodyJSON );
          var result = bodyJSON.LessonName;
          console.log('result:-> ' + result );
          return result;
      });
      response.on('error', callback);
  })
  .on('error', callback)
  .end();
  // end() should be placed above so that the control know we are done with the request and it can now send it to server
}

Can anyone please tell what I'm doing wrong here.

Janmajay
  • 49
  • 1
  • 9
  • 1
    You shouldn't be returning `result` you should be passing it to the callback. Right now you only call the `callback` function when there is an error. You need to call `callback` when the call succeeds also. I don't recommend trying to learn NodeJS and AWS Lambda at the same time. Python is much easier to learn at the same time because you don't have to deal with asynchronous callbacks. – Mark B Nov 19 '17 at 13:50
  • Hi Mark, can you please make me understand what's the difference in returning the result(expecting it to be handled in the parent function) rather than using the callback function to process the result. – Janmajay Nov 20 '17 at 15:48
  • When you call a function asynchronously the caller can't wait for a returned value. This is why callback functions are used. You are missing a fundamental understanding of how asynchronous function calls work. This is why I suggested writing your function in Python since you wouldn't have to deal with asynchronous calls and returning values will work as you expect it to. – Mark B Nov 20 '17 at 15:53

1 Answers1

0

Please don't return the result. You should use callback to get the result of HTTP call back like below,

    var req = http.get('url', (res) => {
        var body = "";

        res.on("data", (chunk) => {
            body += chunk
        });

        res.on("end", () => {
            var result = JSON.parse(body);
           
            callBack(result)
        });
    }).on("error", (error) => {
        callBack(err);
});
Vijayanath Viswanathan
  • 8,027
  • 3
  • 25
  • 43
  • Hi Vijayanath,thanks for the reply, can you please make me understand what's the difference in returning the result(expecting it to be handled in the parent function) rather than using the callback function to process the result. – Janmajay Nov 20 '17 at 15:51