DialogFlow V2 Webhook-立即获得语音响应,而不是在异步请求之后 [英] DialogFlow V2 Webhook - Expects Speech responses Immediately and not after async requests

查看:72
本文介绍了DialogFlow V2 Webhook-立即获得语音响应,而不是在异步请求之后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个DialogFlow V2 node.js Webhook。

I have a DialogFlow V2 node.js webhook.

我有一个通过Webhook操作调用的意图:

I have an intent that is called with a webhook action:

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插入成功块,如下所示:

Now, if I have an async request which finishes successfully, and I do app.add in the success block like this:

 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");
  }

...然后Dialog Flow不等待语音返回。我在Response对象中收到错误:

... then Dialog Flow does not wait for the speech to be returned. I get the error in the Response object:

  "message": "Failed to parse Dialogflow response into AppResponse, exception thrown with message: Empty speech response",

如何让DialogFlow V2等待Webhook的Async操作完成,而不是立即期待语音响应?

How can I make DialogFlow V2 wait for the Webhook's Async operations to complete instead expecting a speech response immediately?

注意:此问题仅在V2中开始发生。在V1中,询问在异步调用的末尾很好。

NOTE: This problem only started happening in V2. In V1, app.ask worked fine at the tail-end of async calls.

示例应用程序的主映射器正在调用Intent,如下所示:

exampleIntent is being called by the main mapper of the application like this:

let actionMap = new Map();
actionMap.set("my V2 intent name", exampleIntent);
app.handleRequest(actionMap);

我在myClient.someAsyncCall中的异步请求正在使用Promises:

And my async request inside myClient.someAsyncCall is using 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()实际上会发送请求。

The reason it worked in V1 is that ask() would actually send the request.

使用V2,您可以调用 add()多次以相同的回复将所有内容发送给用户。因此,它需要知道何时发送消息。

With V2, you can call add() multiple times to send everything to the user in the same reply. So it needs to know when it should send the message. It does this as part of dealing with the response from your handler.

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

If your handler is synchronous, it sends the reply immediately.

但是,如果您的处理程序是异步的,则它假定您正在返回一个Promise,并等到Promise解析后再发送答复。因此,要处理异步呼叫,您需要返回一个Promise。

If your handler is asynchronous, however, it assumes that you are returning a Promise and waits till that Promise resolves before sending the reply. So to deal with your async call, you need to return a Promise.

由于您的呼叫已经在使用Promises,因此您的状态非常好!重要的是您还返回一个承诺并使用它。所以这样的事情可能是您的异步​​调用(返回Promise):

Since your call is using Promises already, then you're in very good shape! The important part is that you also return a Promise and work with it. So something like this might be your async call (which returns a 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处理程序将类似于

and then your Intent handler would be something like

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
    })
}

这篇关于DialogFlow V2 Webhook-立即获得语音响应,而不是在异步请求之后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆