【问题标题】:MS Bot Framework (Nodejs): Session lifetime and delayed messagesMS Bot Framework (Nodejs):会话生命周期和延迟消息
【发布时间】:2025-12-12 01:30:01
【问题描述】:

这是我第一次尝试使用 Bot Framework (Nodejs)。我想测试延迟消息,例如,我的机器人必须在收到消息后 5 秒后回复。 所以我尝试了这段代码:

var builder = require('botbuilder');

var connector = new builder.consoleconnector().listen();
var bot = new builder.universalbot(connector);

bot.dialog('/', function (session) {
    if (!session.userData.TimeoutStarted) {
        session.send("I'll answer in 5 seconds");
        session.userData.TimeoutStarted = true;

        setTimeout(function() {
            session.send("Answer after 5 seconds");
            session.userData.TimeoutStarted = false;
        }, 5000);
    } else {
        session.send("Bot is busy");
    }
});

但这不起作用。 setTimeout 内的回调函数触发,但所有与 session 的操作根本不起作用。

所以,我在这里找到了可能的解决方案:How to send message later in bot framework 并重写我的代码:

var builder = require('botbuilder');

var connector = new builder.ConsoleConnector().listen();
var bot = new builder.UniversalBot(connector);

bot.dialog('/', function (session) {
    if (session.userData.Timeout > 0 && Date.now() - session.userData.Timeout > 5000)
        session.userData.Timeout = 0;

    if (!session.userData.Timeout) {
        session.send("I'll answer in 5 seconds");

        var reply = session.message;

        setTimeout(function() {
           reply.text = "Answer after 5 seconds";
           bot.send(reply);
        }, 5000);

        session.userData.Timeout = Date.now();
    } else {
        session.send("Bot is busy");
    }
});

这段代码可以工作,但是有这么多检查看起来很糟糕。所以我有几个问题:

  1. 为什么第一个代码示例不起作用?我猜是会话生命周期的问题,那么什么是会话生命周期?
  2. 在这个例子中如何设置 session.userData?所以在第一个代码示例中,我想在 setTimeout 内的回调函数中设置它,但它也不起作用。
  3. 创建延迟答案的最佳方法是什么?

【问题讨论】:

    标签: botframework


    【解决方案1】:

    我刚刚调查了这个问题。看起来ConsoleConnector 中存在一个错误,导致无法使用相同的session 对象发送两条消息(由于内部批处理,消息之间的间隔超过了给定的间隔)。由于状态也在send 期间保持不变,因此您的延迟状态更新也将不起作用。如果您在setTimeout 的回调中添加了对session.save 的调用,它将保持新状态(但仍不会发送消息)。

    我相信您的第一个示例应该适用于 ChatConnector(虽然还没有机会尝试)。我将创建一个拉取请求,并修复 ConsoleConnector

    我希望这能回答你所有的问题。

    更新

    有关更多详细信息,请参阅this issue 和相关的拉取请求。

    更新2

    它适用于ChatConnector,使用以下代码:

    var server = restify.createServer();
    server.listen(process.env.port || process.env.PORT || 3978, function () {
    console.log('%s listening to %s', server.name, server.url); 
    });
    
    var connector = new builder.ChatConnector({
        appId: '',
        appPassword: ''
    });
    
    var bot = new builder.UniversalBot(connector);
    
    server.post('/api/messages', connector.listen());
    
    
    bot.dialog('/', function (session) {
        if (!session.userData.TimeoutStarted) {
            session.send("I'll answer in 5 seconds");
            session.userData.TimeoutStarted = true;
    
            setTimeout(function() {
                session.send("Answer after 5 seconds");
                session.userData.TimeoutStarted = false;
            }, 5000);
        } else {
            session.send("Bot is busy");
        }
    });
    

    【讨论】:

    • 感谢您的参与!我用 ChatConnector 对其进行了测试,这是同样的问题:它既不发送消息也不在回调中保存状态。但是会话可以处理不止一个发送。因此,例如,如果我刚刚收到消息并尝试序列: session.send("a"); session.send("b"); - 有效;
    • 你确定吗?它适用于我使用 ChatConnector,请参阅我的更新。关于排序:我说的不是很准确,但是你可以在 GitHub issue 中看到解释。基本上,会话对象默认进行批处理,即它在发送当前消息之前等待 250 毫秒以获取其他消息。这就是为什么它适用于您的排序,但如果您在第一条消息后等待 5000 毫秒,它就不起作用。
    • 抱歉回答晚了。我再次测试它,你是绝对正确的。它确实适用于 ChatConnector。感谢您的帮助!
    【解决方案2】:

    对于有兴趣从机器人发送延迟消息的人,您可以使用session.delay(<ms>)

    例如,

    session.send('msg')
    session.delay(5000) // delay 5 seconds 
    session.endDialog()
    

    【讨论】: