我正在尝试使用DialogFlow
构建一个简单的聊天机器人。
我的目的是从用户问题中提供信息,例如:在克罗地亚,我在哪里可以放宽水面?我有两个参数(croatia
,waterline
)和一个松弛线位置列表。
因此,我需要一个数据库来从参数检索信息。 DialogFlow允许使用Firebase
来实现。我建立了一个包含地点(名称,国家/地区,闲置类型)的数据库,并启用webhook
调用来表达我的意图。
我使用内联编辑器和 index.js
const parameters = request.body.queryResult.parameters;
var country = parameters.country.toString();
function show(snap) {
console.log('snap');
agent.add(JSON.stringify(snap.val(),null,2));
}
function slkplc(agent) {
var testRef;
firebase.database().ref('slackplace').once('value',show);
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('slack place', slkplc);
agent.handleRequest(intentMap);
但是在DialogFlow或Google Assistant上尝试时没有得到预期的结果。函数show被异步调用,但为时已晚,并且响应不适用于 DialogFlow :
我看到了解决此问题的三种方法:
我选择的第三个,但是总是出错。
尝试了几件事以等待数据库响应中的数据后,我唯一要做的就是冻结响应,因此DialogFlow的超时时间为5s,而Firebase的超时时间为60s。
解决方法
另一种实现方法是将数据库获取和请求/响应与DialogFlow分开。数据库数据是在dialogflowFirebaseFulfillment
var data;
var inidata = firebase.database().ref().on('value',function(snap) {
console.log('snap');
data = snap.val();
});
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
...
function slkplc(agent) {
agent.add(JSON.stringify(data,null,2));
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('slack place', slkplc);
agent.handleRequest(intentMap);
}
现在我可以使用数据做我想做的事,而且我能够找到可以在克罗地亚练习吃水线的地方。但是总有些奇怪,数据库的数据是重复的...
答案 0 :(得分:2)
“正确”的解决方案是您建议的选项2:由于您正在执行异步调用,因此在使用dialogflow-fillfillment库时,您需要正确处理此问题。
基本上,如果您的处理程序进行了异步调用,则它也必须是异步的。要向handleRequest()
方法指示处理程序是异步的,您需要返回一个Promise对象。
Firebase的once()
方法如果未传递回调函数,则会返回Promise。您可以利用此功能,返回承诺,并作为.then()
子句的一部分来处理您希望它执行的操作。它可能看起来像这样:
function slkplc(agent) {
var testRef;
return firebase.database().ref('slackplace').once('value')
.then( snap => {
var val = snap.val();
return agent.add( JSON.stringify( val, null, 2 ) );
});
}
重要的部分不仅在于您使用Promise,而且还归还了Promise。