0

Building an Alexa skill that requires persistence.

I am calling the database to get the user details prior to managing the flow and I'm struggling to get Node to wait for the response from DynamoDB (using Dynasty.js to handle the db connectivity).

I've tried a whole host of different promise/callback/node "blocking"/async approaches and the best I can do is have the response (in CloudWatch logs) appear when the user quits the skill. I'd really like the user configuration to happen at the start of the process, rather than at the end!

var credentials = {
    accessKeyId: process.env.MY_ACCESS_KEY_ID,
    secretAccessKey: process.env.MY_SECRET_ACCESS_KEY
};

var dynasty = require('dynasty')(credentials);
var tableName = dynasty.table('dynamoTable');

const promiseFunc = new Promise((resolve,reject)=>{
  var myUser = tableName.find(userId);
  setTimeout(_=>{resolve(myUser)}, 2000);
});

var checkUser = async function(){
 if (true) {
  console.log('check, check, 1, 2, 3');
  await promiseFunc.then(function(myUser) {
   if (myUser) {
    console.log("USER FOUND");
    console.log(myUser);
   } else {
    console.log("no user! sigh deeply and start again");
   }
  })
 }
 console.log("do more stuff now");
}

exports.handler = function(event, context) { 
 
  userId = event.session.user.userId;
 const alexa = Alexa.handler(event, context);
 
  // only check the first time, and only once the userId is properly constructed
 if (!(userId.startsWith('amzn1.ask.account.testUser')) && (checkedUser != 1)) {
  checkedUser = 1;
  checkUser();
 }
 
 alexa.resources = languageString;
 alexa.registerHandlers(newSessionHandlers, startStateHandlers, triviaStateHandlers, helpStateHandlers, stopStateHandlers);
 alexa.execute();
};

How do I get node to wait for the response from dynamoDB before the rest of the script runs...

midtempo
  • 1
  • 3

1 Answers1

0

This is an old-ish link, but according to it, you can get a promise from DynamoDB with the .promise() method. With that in mind...

function findUser(userId) {
    // initialize tableName somehow
    return tableName.find(userId)
}

async function checkUser() {
    // initialize userId somehow
   let myUser = await findUser(userId);
   console.log(`found user ${myUser}`);
   return myUser;
}

Finally, remember to await on your call to checkUser()...

if (/* long condition */) {
    checkedUser = 1;
    let myUser = await checkUser();
}
danh
  • 62,181
  • 10
  • 95
  • 136
  • Dynasty.js has its own promise hooks - [link](http://dynastyjs.com/getting-started/promises.html) - but neither this, nor the approach above, seems to work. Thank you for taking the time to look. m – midtempo Oct 10 '18 at 09:24
  • @midtempo - that intro to promises article seems to indicate that find() returns a promise. That would mean you can omit the `.promise()` in my answer (edited to show that). If that's not working, maybe you ought to build a minimal example (like my answer). find something that you know is in the db with hard-coded params and log it. Work up from there. – danh Oct 10 '18 at 14:13
  • @midtempo - also noticed incidentally that you failed to await on the call to your async function. – danh Oct 10 '18 at 14:19