我很熟悉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();
}
});
但对我来说这似乎不太实用!
答案 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');
})
},
};