我有一个DialogFlow V2 node.js Webhook。
我有一个通过webhook动作调用的意图:
const { WebhookClient } = require('dialogflow-fulfillment'); const app = new WebhookClient({request: req, response: res}); function exampleIntent(app) { app.add("Speak This Out on Google Home!"); // this speaks out fine. no error. }
现在,如果我有一个成功完成的异步请求,并且 在成功块中 执行了 app.add, 如下所示:
function exampleIntent(app) { myClient.someAsyncCall(function(result, err) { app.add("This will not be spoken out"); // no dice :( } // app.add("but here it works... so it expects it immediately"); }
…则对话流不等待语音返回。我在Response对象中收到错误:
"message": "Failed to parse Dialogflow response into AppResponse, exception thrown with message: Empty speech response",
如何让DialogFlow V2等待Webhook的Async操作完成,而不是立即等待语音响应?
注意:此问题仅在V2中开始发生。在V1中,app.ask在异步调用的末尾工作良好。
例如,应用程序的主映射器将调用exampleIntent,如下所示:
let actionMap = new Map(); actionMap.set("my V2 intent name", exampleIntent); app.handleRequest(actionMap);
我的myClient.someAsyncCall内部的异步请求正在使用Promises:
exports.someAsyncCall = function someAsyncCall(callback) { var apigClient = getAWSClient(); // uses aws-api-gateway-client apigClient.invokeApi(params, pathTemplate, method, additionalParams, body) .then(function(result){ var result = result.data; var message = result['message']; console.log('SUCCESS: ' + message); callback(message, null); // this succeeds and calls back fine. }).catch( function(error){ console.log('ERROR: ' + error); callback(error, null); }); };
它在V1中起作用的原因是ask()实际上会发送请求。
ask()
使用V2,您可以add()多次调用以同一回复将所有内容发送给用户。因此,它需要知道何时发送消息。它是处理处理程序响应的一部分。
add()
如果您的处理程序是同步的,它将立即发送答复。
但是,如果您的处理程序是异步的,则它将假定您正在返回一个Promise,并等待该Promise解析之后再发送答复。因此,要处理异步调用,您需要返回一个Promise。
由于您的呼叫已经在使用Promises,因此您的状态非常好!重要的是您还要 返回 Promise并使用它。因此,这样的事情可能是您的异步调用(返回了Promise):
exports.someAsyncCall = function someAsyncCall() { var apigClient = getAWSClient(); // uses aws-api-gateway-client return apigClient.invokeApi(params, pathTemplate, method, additionalParams, body) .then(function(result){ var result = result.data; var message = result['message']; console.log('SUCCESS: ' + message); return Promise.resolve( message ); }).catch( function(error){ console.log('ERROR: ' + error); return Promise.reject( error ); }); };
然后您的Intent处理程序将类似于
function exampleIntent(app) { return myClient.someAsyncCall() .then( function( message ){ app.add("You should hear this message": message); return Promise.resolve(); }) .catch( function( err ){ app.add("Uh oh, something happened."); return Promise.resolve(); // Don't reject again, or it might not send the reply }) }