如何在 Bot Framework v4 中的两个步骤之间有延迟?

How to have delay between two steps in Bot Framework v4?

我想要这样的对话流程 步骤 1 -> 延迟 -> 步骤 2

async step1(stepContext) {
    await stepContext.context.sendActivity('Give user some task to do');
    return await stepContext.next();
    }
    
async delay(stepContext) {
    await stepContext.context.sendActivity({type: 'delay', value:5000});
    return await stepContext.next();
    }

async step2(stepContext) {}

以上代码无法正常工作。当我 运行 机器人等待 5 秒,然后执行 step1 和 step2。我希望延迟在步骤 1 之后。

实际上,我希望延迟为 2 分钟。我想知道机器人不会继续睡觉什么的。对不起,我是新手。

我认为使用瀑布对话框实现此目的的最佳方法是使用 setTimeout 和主动消息。我将在这里做出一些假设,即您熟悉对话状态、Bot 框架适配器和 Turn Handlers 等内容,但如果您需要任何进一步的指导,请告诉我。

首先,从根本上说,您将需要捕获对话参考以发送主动消息。我发现这最简单,只需在您的 onTurn 函数中执行并将其保存到会话状态,如下所示:

const conversationData = await this.dialogState.get(context, {});
conversationData.conversationReference = TurnContext.getConversationReference(context.activity);
await this.conversationState.saveChanges(context);

现在,您可以按如下方式设置对话框。您可能可以通过几种不同的方式来做到这一点。我通常会尝试让每个步骤都成为一个提示,但您可以切换这些操作,但仍然可以正常工作。

async step1(stepContext) {
    // First give the user the task
    await stepContext.context.sendActivity('Give user some task to do');
    
    // Next set up a timeout interval. The action here is to send a proactive message.
    const conversationData = await this.dialogState.get(stepContext.context, {});
    this.inactivityTimer = setTimeout(async function(conversationReference) {
        try {
            const adapter = new BotFrameworkAdapter({
                appId: process.env.microsoftAppID,
                appPassword: process.env.microsoftAppPassword
            });
            await adapter.continueConversation(conversationReference, async turnContext => {
                await turnContext.sendActivity('Were you able to successfully complete the task?');
            });
        } catch (error) {
            //console.log('Bad Request. Please ensure your message contains the conversation reference and message text.');
            console.log(error);
        }
    }, 120000, conversationData.conversationReference);

    // Give the user a confirmation prompt
    return await stepContext.prompt('choicePrompt', 'Please confirm the results of the task when you are finished',['Passed','Failed']);
}

async step2(stepContext) {

    // Clear timeout to prevent the proactive message if user has already responded
    clearTimeout(this.inactivityTimer);

    /* REST OF YOUR DIALOG HERE */

    return await stepContext.endDialog();

}

如前所述,确保您正在导入 Bot Framework Adapter、设置提示(我使用了 choice 但显然它可以是任何内容)、导入对话状态等。另外,需要注意的一件事是如果用户响应非常接近计时器(我在此处设置为 2 分钟),则可能会在 bot 到达 clearTimeout 语句之前调用主动消息。我认为这最多是一件烦人的事,但您需要根据某人在将近 2 分钟内完成任务的频率来确定该用户体验是否正常。

最后一点,您可以将主动消息调用放在一个单独的辅助函数中,特别是如果您要在许多不同的对话框中使用它。这样您就不必创建适配器的多个实例,此外还能使您的代码更易于更新。也就是说,如果您像我一样只在某个地方需要它,我发现将它插入到对话框中会容易得多,因为它没有那么多代码。