我正在尝试使用 DialogFlow
构建一个简单的聊天机器人 .
我的目的是提供用户问题的信息,例如:克罗地亚哪里可以在水面上松弛?我有两个参数( croatia
, waterline
)和一个松弛线位置列表 .
所以我需要一个数据库来从参数中检索信息 . DialogFlow允许使用 Firebase
实现 . 我用地点(名称,国家,松弛类型) Build 一个数据库,并为我的意图启用 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智能助理上尝试时,我没有得到预期的结果 . 函数show被异步调用但为时已晚,并且 DialogFlow 的响应不可用:
我看到三种方法来处理这个问题:
-
使用阻塞调用数据库:另一个数据库?
-
用DialogFlow处理异步消息???
-
响应用户发生错误 .
我选择的第三个,但总是出错 .
在尝试了几个等待来自数据库响应的数据之后,我唯一能做的就是冻结响应,因此达到了DialogFlow - 5s和Firebase - 60s的超时 .
A workaround
另一种方法是从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);
}
现在我可以用数据做我想做的事情,我能找到我可以在克罗地亚练习水线的地方 . 但总有一些奇怪的东西,数据库的数据是重复的......
1 回答
“正确”的解决方案是您建议的选项2:由于您正在进行异步调用,因此在使用dialogflow-fulfillment库时需要正确处理 .
基本上,如果您的处理程序进行异步调用,它也需要是异步的 . 要向
handleRequest()
方法指示您的处理程序是异步的,您需要返回一个Promise对象 .如果您没有向其传递回调函数,Firebase的
once()
方法将返回Promise . 您可以利用这一点,返回Promise,并处理您希望它作为.then()
子句的一部分执行的操作 . 它可能看起来像这样:重要的部分不仅仅是你使用了Promise,还有你返回Promise .