一尘不染

DialogFlow V2 Webhook-立即获得语音响应,而不是在异步请求之后

node.js

我有一个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);
    });
};

阅读 154

收藏
2020-07-07

共1个答案

一尘不染

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

使用V2,您可以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
    })
}
2020-07-07