【问题标题】:BotFramework Post Request Body not being saved in session.userDataBotFramework Post 请求正文未保存在 session.userData 中
【发布时间】:2019-03-01 01:27:18
【问题描述】:

使用 POST 请求,我将用户提交的信息发送到 API,该 API 将提供用户特定的信息。

现在,我想将 POST 请求反刍的信息保存为我可以在其他函数/对话中使用的变量。

我尝试了以下方法:

  1. 将 POST 请求正文保存在 session.userData.xxx 变量中
  2. 声明了一个全局变量并用它来存储正文。
  3. 在我存储正文的发布请求中声明了一个变量

我做的一个版本的代码如下:

    var body2;

    bot.dialog('FunctionA', [
        function (session) {
            session.sendTyping();
            builder.Prompts.text(session, "Please key-in your App ID:");
    },
    function (session, results) {
        session.userData.AppID= results.response;
         var options = {
      url: 'APIXYZ.COM',
      headers: {
          'Content-Type' : 'application/json'               
            },
         body: JSON.stringify({"appID": session.userData.AppID})

        };

        request.post(options, function(error, response, body) {
          if (!error && response.statusCode == 200) {
            console.log(body); //logs okay
            session.userData.infoA = body;
        console.log(session.userData.infoA) //logs okay
        body2 = body;
            console.log (body2) // logs ok
        var bodyvar = body;
            console.log (bodyvar) //logs ok

          } else {
              console.log("Error: " + error);
              console.log("Status Code: " + response.statusCode);
          }
        });

        var msg = new builder.Message(session)

        .text("The body is:" + session.userData.infoA) //outputs "The body is undefined", if body2,bodyvar -> empty
        .suggestedActions(
            builder.SuggestedActions.create(
                session, [

                    builder.CardAction.imBack(session, "Ok", "Ok")
                    builder.CardAction.imBack(session, "No", "No")

                ]
            ));
    session.send(msg).endDialog();

    }]).triggerAction({ matches: /^ABC/i });

它似乎只在请求块内工作,我不能在外面使用它。在其外部使用时,它被记录为未定义。我希望能够将 POST 请求正文存储为变量,以便我可以在此对话之外使用它们并将其保存在数据库中。

谢谢!

编辑:

我已将 body2 声明为对话框和请求块之外的变量,并在同一对话框中使用了该变量,就在 request.post 之后

var msg = new builder.Message(session)

.text("The body contains: " + body2 + " .") 
        .suggestedActions(
            builder.SuggestedActions.create(
                session, [

                    builder.CardAction.imBack(session, "Ok", "Ok")
                    builder.CardAction.imBack(session, "No", "No")

                ]
            ));

这会输出The body contains: undefined .

我也尝试在另一个对话框中使用它:

bot.dialog('Validation', function (session) {
    console.log(body2);
   session.send("The content is : " + body2 +" xx");
    if (body2== "ABC")
    {
        session.sendTyping();
        var msg = new builder.Message(session);
[.......]

这会导致"Oops. Something went wrong and we need to start over" 提示

【问题讨论】:

  • 您试图在请求正文之外访问body2?只要它是在它之外定义的,它就应该可以正常工作。我刚刚测试了一些非常相似的东西并且它有效。您能否发布所有代码并指定您想再次访问body2(或适当的变量)的位置?
  • ...通过“定义”,我的意思是“实例化”。
  • @mdrichardson 我已更新问题以适应我的编辑和附加代码,谢谢!

标签: node.js azure request botframework


【解决方案1】:

问题是您的post 请求在您执行其他功能之前没有完成。换句话说,这就是您的代码正在执行的操作:

  1. 创建post 请求
  2. 执行代码时 body2 仍未定义
  3. post 请求完成,然后body2 定义为 body

您可以通过两种方式解决此问题:

使用异步/等待

这基本上会强制您的所有代码在继续之前等待request.post 返回数据。如果您不熟悉,async/await 是使用Promises.then() 的较新方式。它非常有用,尤其是在发出 HTTP 请求时。你可以read more here

添加async

async function (session, results) {
    session.userData.AppID= results.response;
    var options = {
        url: 'APIXYZ.COM',
...

添加await

await request.post(options, function(error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body); //logs okay
    session.userData.infoA = body;

在请求函数中封装代码

由于request.post 将在具有errorresponsebody 之后执行代码,因此您可以包含任何需要使用返回的数据的代码:

request.post(options, function(error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body); //logs okay
        body2 = body;
        console.log (body2) // logs ok
        var msg = new builder.Message(session)
            .text("The body is:" + body2)
            .suggestedActions(
                builder.SuggestedActions.create(
                    session, [

                        builder.CardAction.imBack(session, "Ok", "Ok"),
                        builder.CardAction.imBack(session, "No", "No")

                    ]
                ));
        session.send(msg).endDialog();
    } else {
        console.log("Error: " + error);
        console.log("Status Code: " + response.statusCode);
    }
});

我推荐使用async/await 路线,原因有两个:

  1. 它在许多 JavaScript 场景中都非常有用,非常值得了解
  2. 如果您在其他对话框中使用body2,无论如何您都需要使用它。使用上面的“封装”方法,您可能仍在等待响应,而另一个需要body2 的对话框启动

话虽如此,您似乎正在使用 Bot Framework 的 V3。如果这是一个新机器人,我建议在 V4 中构建它——它具有更新的功能,我们更好地支持它。

【讨论】:

    猜你喜欢
    • 2017-08-27
    • 1970-01-01
    • 2019-08-06
    • 2019-05-16
    • 2023-04-10
    • 2021-03-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-07
    相关资源
    最近更新 更多