Dialogflow es 使用Dialogflow在对话中存储唯一的usersId(userStorage ERROR在发送给用户后不能设置头)

Dialogflow es 使用Dialogflow在对话中存储唯一的usersId(userStorage ERROR在发送给用户后不能设置头),dialogflow-es,actions-on-google,dialogflow-es-fulfillment,Dialogflow Es,Actions On Google,Dialogflow Es Fulfillment,我正在尝试制作一个Google Home应用程序,并使用在本地服务器上运行的webhook和express.js作为实现。我想在webhook向我的服务器发送post请求时,使用请求中的“request.body.originalDetectIntentRequest.payload.user.userStorage”参数来标识用户。此请求提供的userId等于我为每个用户本地存储的日志文件名,在这里我跟踪每个用户的不同内容 我是从一个医生那里得到处理这种事情的主意的。在囚犯给出的回答中,他谈到

我正在尝试制作一个Google Home应用程序,并使用在本地服务器上运行的webhook和express.js作为实现。我想在webhook向我的服务器发送post请求时,使用请求中的“request.body.originalDetectIntentRequest.payload.user.userStorage”参数来标识用户。此请求提供的userId等于我为每个用户本地存储的日志文件名,在这里我跟踪每个用户的不同内容

我是从一个医生那里得到处理这种事情的主意的。在囚犯给出的回答中,他谈到了你必须回复的重要性。到目前为止还不错,我试图在代码中实现这一点,在生成新用户ID后发送响应,但我一直收到相同的错误:

(node:21236) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:518:11)
所以这可能与我有一行agent.handleRequest(intentMap)有关在我的代码末尾,它将处理请求并将响应发送回用户本身

我如何解决这个问题?我已经试图找到这个问题的解决方案,但是在尝试了不同的方法之后,我只能想到一件事,那就是在发送带有payload.google.userStorage变量的响应之前扩展响应,尽管我尝试了response.write,但这给了我同样的错误

我的代码:

  app.post('/', express.json(), (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));
  
  let userStorage = request.body.originalDetectIntentRequest.payload.user.userStorage || JSON.stringify({});
  let userId;
  console.log("userStorage", userStorage);
  userStorage = JSON.parse(userStorage);
  console.log("userStorage_after_parsing", userStorage);
  if (userStorage.hasOwnProperty('userId')) {
      userId = userStorage.userId;
      console.log('user was already defined:' + userId);
  } else {
    let uuid = require('uuid/v4');
    checkNewUser = true;
    userId = uuid();
    userStorage.userId = userId
    console.log(userId);
    response.send({
      'payload': {
        'google': {
          'userStorage': JSON.stringify(userStorage)
        }
      }
    }
    );
//rest of the code
agent.handle(intentMap)
更新问题:

在囚犯的回答之后,我决定将handleWelcome意图的代码包括在其中,我希望将代码粘贴到其中,以使用userStorage变量扩展响应:

      function handleWelcome(agent) {
    //code to add userStorage to the response?
    if (checkIfUserVerified() === true) {
      agent.add('Hi.');
      //updateLog('User just said hi.');
      let userObj = readJsonSync(userId + '.json');
      userObj.logs.push('User just started talking to this chatbot ' + getCurrentDateTime());
      fs.writeFileSync(userId + '.json', JSON.stringify(userObj));
    }
    else {
      close('Please make sure you are a verified user before using this version of SMART4MD. To do so, read the SMART4MD Voice assistant manual.');
      agent.setFollowupEvent('GOODBYE');
    }
  } 

注意你在回答中提到的评论

// Make sure you include the userStorage as part of the response
响应的“部分”——而不是响应本身。在代码中,在调用意图处理程序之前,您将发送回JSON以发送到用户存储。一旦发送了某个内容,连接就会关闭,因此无法再发送任何内容,包括您想要的回复。这就是为什么会出现错误


您没有显示任何Intent处理程序函数,因此很难给出确切的答案,但一般的解决方案是将
userStorage
中的userid设置为每个处理程序调用的函数的一部分。

感谢您的评论!如果我理解正确,那么可以添加userStorage变量,以便在我触发欢迎意图时处理的函数中进行应答?当我和我的google home speaker通话并说‘嘿,google,talk to…’时,欢迎意向会自动触发,所以如果我没有弄错的话,这将是添加这部分响应的完美功能?我将使用handleWelcome函数更新我的问题,该函数在识别欢迎意图时触发。我已将该函数添加到我的问题中。我的问题还是一样的。如何在发送响应之前向其添加内容?经过一些跟踪和错误之后,我似乎仍然不明白如何向响应添加userStorage变量。我试着像“response.payload.google=JSON.stringify(userStorage)”这样做,但现在我得到了错误“无法读取未定义的google属性”。如果我没弄错的话,每个webhook响应主体都包含一个有效负载?您在原始帖子中将其声明为对象,但是我应该如何处理该对象才能真正附加响应?您知道如何将此变量添加到响应中吗?我一直在尝试agent.add,也一直在研究使用google library上的操作来制作app.intent(conv=>以便我可以使用conv对象将其存储在中,但这给了我其他错误,因为我仍然在使用dialogflow库…我没有想法请启发我。