【问题标题】:DialogFlow V2 Webhook - Expects Speech responses Immediately and not after async requestsDialogFlow V2 Webhook - 立即而不是在异步请求之后期望语音响应
【发布时间】:2018-03-19 14:38:03
【问题描述】:

我有一个 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 的异步操作完成,而不是立即期待语音响应?

注意:此问题仅在 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);
    });
};

【问题讨论】:

  • 您能否更新您的问题以包括您如何调用exampleIntent() 函数?
  • 我已经做到了。 exampleIntent 由映射到 DialogFlow 中的 Intent Name 的主映射器调用。然后“someAsyncCall”在后台使用 AWS 库和承诺。我基本上需要让我的 webhook 等待响应......

标签: node.js actions-on-google dialogflow-es api-ai


【解决方案1】:

它在 V1 中起作用的原因是 ask() 实际上会发送请求。

使用 V2,您可以多次调用 add() 以在同一个回复中将所有内容发送给用户。所以它需要知道什么时候应该发送消息。它作为处理来自您的处理程序的响应的一部分来执行此操作。

如果您的处理程序是同步的,它会立即发送回复。

但是,如果您的处理程序是异步的,则它假定您正在返回一个 Promise 并等待该 Promise 解决后再发送回复。所以要处理你的异步调用,你需要返回一个 Promise。

既然你的调用已经使用了 Promises,那么你的状态就很好了!重要的部分是您还 return 一个 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
    })
}

【讨论】:

  • 如何使我的处理程序同步或异步?某处是否有按意图设置?
  • 根据您在其中执行的操作,您可以使处理程序同步或异步。如果你在里面做异步工作,你必须返回一个做异步工作的 Promise。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-30
  • 1970-01-01
  • 1970-01-01
  • 2019-05-28
相关资源
最近更新 更多