1

Preface: I'm new to JavaScript. If this question is startlingly stupid, that's (part of) the reason.

Begin Update

I found the answer to my question prior to the flag as a dupe. I solved it with a try-catch block. This answer does not reference a try-catch block.

How do I return the response from an asynchronous call?

End Update

I'm attempting to create an Alexa project from scratch (well, at least without one of Amazon's templates). I've written the "guts" of the app and I've tested my functions with chai. Things were going swimmingly until I tried to wire up some intents.

I can see my intents are being sent based on console.log statements I've thrown in the helperClass, but the return values aren't making it back to my index.js file.

Two questions:

  1. What am I mucking up?
  2. How do I fix it?

Here's what I've done: Based on that, I dug around to see what's going on in my index.js file's headers and I saw this:

var Alexa = require('alexa-app');

So I went to alexa-app and saw that it uses bluebird, which suggests to me that I'm dealing with a promise problem. Further, I saw this in the log when I send a request that works:

preRequest fired
postRequest fired

When a request doesn't work, I only see:

preRequest fired

I'm using Big Nerd Ranch's "Developing Alexa Skills Locally with Node.js".

Here's my problematic intent in my index.js file:

app.intent('getDaysFromNow', {
  'slots': {
        'INPUTDATE' : 'AMAZON.DATE'
  },
    'utterances': ['{|number of|how many} {days} {until|from|since} {|now|today} {|is|was} {-|INPUTDATE}'] // almost perfect
},
  function(req, res) {
    console.log('app.intent getDaysFromNow fired');
    //get the slot
    var inputDate = req.slot('INPUTDATE');
    var reprompt = 'Ask me how many days until or from a specified date.';
    if (_.isEmpty(inputDate)) {
        console.console.log('app.intent daysFromNow blank request');
      var prompt = 'I didn\'t hear the date you want.';
      res.say(prompt).reprompt(reprompt).shouldEndSession(false);
      return true;
    } else {
        console.log('getDaysFromNow slot is not empty.');
      var dateHelper = new DateHelper();
      dateHelper.getDaysFromNow(inputDate).then(function(daysFromNow) { 
        console.log(daysFromNow);
        res.say(dateHelper.formatDaysFromNowResponse(daysFromNow)).send(); // FIXME
      }).catch(function(err) {
        console.log(err.statusCode);
        var prompt = 'Hmm...I don\'t have a date for that ' + inputDate;
        res.say(prompt).reprompt(reprompt).shouldEndSession(false).send();
      });
      return false;
    }
  }
);

I know it's getting sent, but the value's not getting back to index.js. I think I've got a return problem. Here's the function in my helperClass.js whose return isn't getting back to index.js

    // Takes AMAZON.DATE string as its argument
DateHelper.prototype.getDaysFromNow = function(inputDate) {

    if (isValidDate(inputDate)) {       // validate it
        // if it's valid, run the function
        inputDate = moment(inputDate, "YYYY-MM-DD").startOf('day'); // inputDate starts as a string, recast as a moment here
        // create currentDate moment from current Date()
        var currentDate = moment(new Date()).startOf('day');

        // Calculate daysFromNow here
        var daysFromNow = inputDate.diff(currentDate, 'days');
        console.log("\t" + 'daysFromNow = ' + daysFromNow);

        // ORIGINAL CODE
        // return daysFromNow;

        // EXPERIMENTAL CODE
        return this.daysFromNow.then(
            function(response) {
                return response.body;
            }
        );
    } else {
        // throw an error
        throw new Error("getDaysFromNow(): argument must be valid AMAZON.DATE string");
    }
};

Thank you for reading. I welcome your suggestions.

Community
  • 1
  • 1
Adrian
  • 16,233
  • 18
  • 112
  • 180
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – rohithpr Apr 23 '16 at 02:13
  • @rohithpr I answered my own question. – Adrian Apr 23 '16 at 03:26

1 Answers1

-2

It turns out it's not the way the return is sent from helperClass. The issue is how the call was made in the first place.

For the helperClass, I reverted to the original return.

    // This is the return from `helperClass`
    return daysFromNow;

In the index.js class, I put the call to helperClass in a try-catch block, like so:

app.intent('getDaysFromNow', {
  'slots': {
    'INPUTDATE': 'AMAZON.DATE'
  },
  'utterances': ['{|number of|how many} {days} {until|from|since} {|now|today} {|is|was} {-|INPUTDATE}'] // almost perfect
},
  function(req, res) {
    console.log('app.intent getDaysFromNow fired');
    //get the slot
    var inputDate = req.slot('INPUTDATE');
    var reprompt = 'Ask me how many days until or from a specified date.';
    if (_.isEmpty(inputDate)) {
      console.log('app.intent daysFromNow blank request');
      var prompt = 'I didn\'t hear the date you want.';
      res.say(prompt).reprompt(reprompt).shouldEndSession(false);
      return true;
    } else {
      // ** CHANGED: This is the part that changed. **
      console.log('getDaysFromNow slot is not empty.');
      var dateHelper = new DateHelper();
      try {
        var daysFromNow = dateHelper.getDaysFromNow(inputDate);
        res.say(dateHelper.formatDaysFromNowResponse(daysFromNow)).send(); 
      } catch (error) {
        console.log("error", error);
        var prompt = 'Hmm...I don\'t have a date for that ' + inputDate;
        res.say(prompt).reprompt(reprompt).shouldEndSession(false).send();
      }
      return false;
    }
  }
);

Hopefully, someone finds this helpful if they run into the same problem.

Adrian
  • 16,233
  • 18
  • 112
  • 180