DialogflowSDK 中间件 return 解决承诺后

DialogflowSDK middleware return after resolving a promise

我目前正在使用 actions-on-google node sdk,我正在努力弄清楚如何等待承诺在我的中间件中解决,然后再执行我的意图。我试过使用 async/await 和 returning a promise 从我的中间件功能,但两种方法似乎都不起作用。我知道通常你不会像我在这里做的那样覆盖意图,但这是为了测试发生了什么。

const {dialogflow} = require('actions-on-google');
const functions = require('firebase-functions');

const app = dialogflow({debug: true});

function promiseTest() {
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve('Resolved');
        }, 2000)
    })
}
app.middleware(async (conv) => {
    let r = await promiseTest();
    conv.intent = r
})

    app.fallback(conv => {
    const intent = conv.intent;

    conv.ask("hello, you're intent was " + intent );
});

看来我至少应该能return一个promisehttps://actions-on-google.github.io/actions-on-google-nodejs/interfaces/dialogflow.dialogflowmiddleware.html

但我不熟悉打字稿,所以我不确定我是否正确阅读了这些文档。

任何人都可以建议如何正确地做到这一点?例如,现实生活中的示例可能是我需要进行数据库调用并等待它在我的中间件中 return,然后再继续下一步。

我的函数在 google 云函数中使用 NodeJS V8 beta。

此代码的输出是任何实际意图,例如默认的欢迎意图,而不是 "resolved",但没有错误。因此,中间件会触发,但会在 promise 解决之前转移到回退意图。例如在设置 conv.intent = r

之前

异步功能对于 V2 API 来说真的很麻烦。对我来说,只能正确使用 NodeJS 8。原因是从 V2 开始,除非你 return 承诺,否则操作 return 是空的,因为它在函数的其余部分被评估之前已经完成。有很多工作要做才能弄清楚,这里有一些示例样板,应该可以帮助您:

'use strict';

const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {BasicCard, MediaObject, Card, Suggestion, Image, Button} = require('actions-on-google');
var http_request = require('request-promise-native');

process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });
  console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
  console.log('Dialogflow Request body: ' + JSON.stringify(request.body));

  function welcome(agent) {
    agent.add(`Welcome to my agent!`);
  }

  function fallback(agent) {
    agent.add(`I didn't understand`);
    agent.add(`I'm sorry, can you try again?`);
  }

  function handleMyIntent(agent) {
      let conv = agent.conv();
      let key = request.body.queryResult.parameters['MyParam'];
      var myAgent = agent;
      return new Promise((resolve, reject) => {
        http_request('http://someurl.com').then(async function(apiData) {
          if (key === 'Hey') {
            conv.close('Howdy');
          } else {
            conv.close('Bye');
          }
          myAgent.add(conv);
          return resolve();
      }).catch(function(err) {
          conv.close('  \nUh, oh. There was an error, please try again later');
          myAgent.add(conv);
          return resolve();
      })})
  }

  let intentMap = new Map();
  intentMap.set('Default Welcome Intent', welcome);
  intentMap.set('Default Fallback Intent', fallback);
  intentMap.set('myCustomIntent', handleMyIntent);
  agent.handleRequest(intentMap);
});

您需要什么的简要概述:

  • 您必须 return 承诺决议。
  • 您必须为 HTTP 请求使用 'request-promise-native' 包
  • 您必须升级计划以允许出站 HTTP 请求(https://firebase.google.com/pricing/)

原来我的问题与 actions-on-google sdk 的过时版本有关。 dialogflow firebase 示例使用的是 v2.0.0,在 package.json 中将其更改为 2.2.0 解决了问题