简体   繁体   English

使用Lambda nodejs从DynamoDB读取Alexa Skill

[英]Read from DynamoDB with Lambda nodejs for Alexa Skill

Iam new to Skill and nodejs development and got my first problem very soon. 我是Skill和nodejs开发的新手,很快就遇到了我的第一个问题。

Basically, iam trying to read data from DynamoDB and let it speak over Alexa. 基本上,我试图从DynamoDB读取数据并让它通过Alexa说话。

var title;

exports.handler = (event, context, callback) => { 
    getData();
    alexa = Alexa.handler(event, context, callback); 
    alexa.appId = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();     
};

const handlers = {
    'LaunchRequest': function () {
        this.emit('DoSomethingIntent');
    },
    'DoSomethingIntent': function () {      
        this.response.speak('Here are your data ' + title);
        this.emit(':responseReady');        
    },
};

function getData() {
    var ddb = new AWS.DynamoDB.DocumentClient({region:'eu-west-1'});
    var params = {
        TableName: 'data', 
        Key: {'data_id' : 1,},
    };      
    ddb.get(params, function(err, data) {
        if (err) {
        }else{
           title = data.Item.title;             
        }
    });
}

The problem is that the DynamoDB.DocumentClient.get function is running asynchron and at the same time when the DoSomethingIntent runs the title variable is undefined. 问题是DynamoDB.DocumentClient.get函数是异步运行的,同时当DoSomethingIntent运行时,标题变量是未定义的。

What would be the best practice to solve this problem? 解决这个问题的最佳做法是什么?

The only Solution which has worked for me so far was that: 迄今为止唯一对我有用的解决方案是:

ddb.get(params, function(err, data) {
    if (err) {

    }else{
        title = data.Item.title;                                      
        alexa.registerHandlers(handlers);
        alexa.execute(); 
    }
});

But it does not seem very practical for me! 但它对我来说似乎不太实用!

Your working solution is correct because if you write the execution logic then it will run before it completes Dynamodb callback. 您的工作解决方案是正确的,因为如果您编写执行逻辑,那么它将在完成Dynamodb回调之前运行。 Please remember DynamoDB call is Asynchronous non-blocking I/O so it will not block any code to execute outside the callback. 请记住DynamoDB调用是异步非阻塞I / O,因此它不会阻止任何代码在回调之外执行。 So better place to add Alexa execution logic is inside callback. 因此,在回调中添加Alexa执行逻辑的更好位置。

This is happening because ddb.get() function is asynchronous and callback is running after execution of your handler. 发生这种情况是因为ddb.get()函数是异步的,并且在执行处理程序后回调正在运行。 So there is no certainty of variable title getting populated before your response is sent. 因此,在发送响应之前,不确定变量title是否已填充。

You can use native promise here. 你可以在这里使用原生承诺。

Modify your getData function like below: 修改你的getData函数,如下所示:

function getData() {
  var ddb = new AWS.DynamoDB.DocumentClient({region:'eu-west-1'});
  var params = {
      TableName: 'data', 
      Key: {'data_id' : 1,},
  };

  return new Promise((resolve,reject) => {
    ddb.get(params, function(err, data) {
        if (err) {
        }else{
          title = data.Item.title;
          resolve(title);       
        }
    });
  })
}

And do following changes in your handler function and response handler: 并在处理程序函数和响应处理程序中执行以下更改:

exports.handler = (event, context, callback) => { 
    // Remove getData() from here
    alexa = Alexa.handler(event, context, callback); 
    alexa.appId = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();     
};

const handlers = {
    'LaunchRequest': function () {
        this.emit('DoSomethingIntent');
    },
    'DoSomethingIntent': function () {
      getData()
      .then( (title) => {
        this.response.speak('Here are your data ' + title);
        this.emit(':responseReady'); 
      })
      .catch( (error) => { // Handler error gracefully
        console.log(error);
        this.response.speak('Something is wrong. Try later.')
        this.emit(':responseReady');
      })
    },
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM