在开发语音应用程序时映射数据流时无法处理其他情况

Trouble handling else condition when mapping data stream while developing voice app

我目前正在开发一个带有 Google 动作的语音应用程序。基本上,用户必须在以下 data stream 中询问信息,语音应用程序应根据该数据流中的信息进行回复。目前,应用程序可以根据以下代码匹配用户的请求和流中的数据:

// From here, there are all the required libraries to be loaded
const { conversation } = require('@assistant/conversation'); // This the app coversation
const functions = require('firebase-functions'); //These are the firebase functions
require('firebase-functions/lib/logger/compat'); // console.log compact
const axios = require('axios'); // This is axios to retrieve the data stream
// To here, there all the required libraries to be loaded

const app = conversation({debug: true}); // This instantiate the conversation

/* This function retrieve the data from the file stream */
async function getItem() {
    const res = await axios.get('https://sheetdb.io/api/v1/n3ol4hwmfsmqd');
   return res.data; // To use in your Action's response
}

/* This is the fuction to match user's responses and data stream*/
app.handle('getItem', async conv => { //getItem is the weekhook name used in Google Actions, conv is the conversation
  const data = await getItem(); // Here the data stream is retrieved and send to the data variable
//   console.log(data);
  const itemParam = conv.intent.params.Item.resolved; // This is the user's response, in other words, what item the user's want to know from the data.
  const itemIDParam = conv.intent.params.Item_ID.resolved.replace(/\s/g, ''); //This is the user's response for item ID
  const itemFromUser = itemParam + " " + itemIDParam;
  console.log(itemParam);
  console.log(itemIDParam);
  console.log(itemFromUser);
//   conv.add(`This test to see if we are accessing the webhook for ${itemParam}`); // This is to know if I was getting the correct item from the user. Currently this is working
//   console.log(data);
    data.map(item  => { //Then, I am trying to map the data stream to recognize the data headers and identify items
//     console.log(data);
//     console.log(item);
      if (item.Name.toLowerCase() === itemFromUser.toLowerCase()){
        console.log(item);
        conv.add(`These are the details for ${itemFromUser}. It is located in zone ${item.Zone}, at level ${item.Level}.`);
//         console.log(conv);
//          console.log(data);
      } 
    else {
      conv.add(`I am sorry. I could not find any information about that object. Please try with another construction object.`);
      }
  });
});

exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

data.map 函数有一个 if else 语句来管理何时匹配数据,何时不匹配。

    data.map(item  => { //Then, I am trying to map the data stream to recognize the data headers and identify items
//     console.log(data);
//     console.log(item);
      if (item.Name.toLowerCase() === itemFromUser.toLowerCase()){
        console.log(item);
        conv.add(`These are the details for ${itemFromUser}. It is located in zone ${item.Zone}, at level ${item.Level}.`);
//         console.log(conv);
//          console.log(data);
      } 
    else {
      conv.add(`I am sorry. I could not find any information about that object. Please try with another construction object.`);
      }
  });

当条件为真时,if 在没有else 语句的情况下起作用。但是由于某些原因,当添加 else 语句并且数据没有匹配到任何用户时,它使应用程序表现得很奇怪,在控制台中显示以下错误:

Error: Error adding simple response: Two simple responses already defined

无论数据是否匹配,我都会收到此错误。

我正在做的测试是评论 else 语句。这使我能够获得数据的匹配项,但当数据不匹配时应用程序会原地切入。但理想情况下,我希望应用程序告诉用户查询没有找到任何匹配项。

在此先感谢,我希望有人能给我一些提示。

您看到的错误是:

Error: Error adding simple response: Two simple responses already defined

您的操作响应只能包含 two simple responses。例如,每个响应都呈现为 phone 上的单独文本气泡。

所以看起来 item.Name === itemParam 可能 运行 一次,但在 else 条件下你最终会创建太多。您可能想要 re-evaluate 如何 运行 您的条件。

但据我所知,有两种快速方法可以解决此问题:

字符串生成器方法

在这种方法中,您可以在循环之前创建一个字符串变量,而不是立即添加到 conv,您只需继续附加到字符串直到完成。然后你添加整个东西。

这种方法的缺点是无论如何您最终都可能会得到一个巨大的字符串,并且平台将运行将字符串分类为最多 640 个字符。

app.handle('getItem', async conv => {
  const data = await getItem();
  const itemParam = conv.intent.params.Item.resolved;
  
  let res = '';
  data.map(item  => {
      if (item.Name === itemParam);
        res += `These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`;
  });
  if (res !== '') {
    conv.add(res);
  } else {
    conv.add('No items were found.')
  }
});
提前退出方法

您还可以将循环编写为不使用函数式编程方法,而是识别条件为真的第一个实例,然后提前退出处理程序。这将使您进入 for-of 循环,然后添加一个 return 来结束执行。

缺点是您的处理程序随后已完成,您将无法执行任何其他逻辑。或者,您可以将此子例程粘贴到它自己的函数中进行调用。然后您自己在处理程序中捕获该响应。

function getItemDetails(data) {
  for (const item of data) {
      if (item.Name === itemParam) {
        return item 
      }
  }
  return undefined
}

app.handle('getItem', async conv => {
  const data = await getItem();
  const itemParam = conv.intent.params.Item.resolved;
  const item = getItemDetails(data)
  if (item !== undefined) {
    conv.add(`These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`); 
  } else {
    conv.add('No items were found.')
  }
});