使用Lambda nodejs从DynamoDB读取Alexa Skill

时间:2017-11-22 09:38:01

标签: javascript node.js amazon-dynamodb aws-lambda alexa

我很熟悉Skill和nodejs开发,很快就遇到了第一个问题。

基本上,iam尝试从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;             
        }
    });
}

问题是DynamoDB.DocumentClient.get函数是异步运行的,同时当DoSomethingIntent运行时,标题变量是未定义的。

解决此问题的最佳做法是什么?

迄今为止唯一对我有用的解决方案是:

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

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

但对我来说这似乎不太实用!

2 个答案:

答案 0 :(得分:1)

您的工作解决方案是正确的,因为如果您编写执行逻辑,那么它将在完成Dynamodb回调之前运行。请记住DynamoDB调用是异步非阻塞I / O,因此它不会阻止任何代码在回调之外执行。因此,在回调中添加Alexa执行逻辑的更好位置。

答案 1 :(得分:1)

之所以发生这种情况,是因为ddb.get()函数是异步的,并且在执行处理程序之后回调正在运行。因此,在发送响应之前,不确定变量title会被填充。

您可以在此处使用本机承诺。

按如下所示修改您的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);       
        }
    });
  })
}

并在处理程序函数和响应处理程序中进行以下更改:

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');
      })
    },
};