如何避免Microsoft Bot Builder SDK中beginDialogAction与triggerAction重复执行
解决Bot Builder中beginDialogAction与triggerAction重复添加对话框的问题
你的问题核心在于同时给同一个匹配规则绑定了beginDialogAction和triggerAction,导致当用户在根对话框中输入匹配内容时,两个动作都会触发:beginDialogAction会将子对话框压入对话栈,而全局的triggerAction又会再添加一个相同的子对话框实例,最终造成子对话框结束后还有重复实例等待运行的情况。
下面提供两种符合你需求的解决方案,既能让用户在任意对话中触发子对话框,又能保证根对话框在子对话框结束后继续执行:
方案一:统一使用triggerAction并配置beginDialog逻辑
这种方案更简洁,只保留全局的triggerAction,但修改它的触发逻辑为压栈式启动子对话框(替代默认的替换栈行为),同时避免重复添加相同对话框:
// 根对话框 bot.dialog('/', [ function (session, args, next) { session.send('Starting root dialog'); }, function (session) { session.send('Ending root dialog.'); } ]); // 用户添加子对话框 bot.dialog('UserAdd', [ function (session, args, next) { session.send('Adding user.'); // 必须调用endDialog结束子对话框,父对话框才能继续执行 session.endDialog(); } ]).triggerAction({ matches: /^user add$/i, onSelectAction: (session, args, next) => { // 检查栈顶是否已经是UserAdd对话框,避免重复添加 const lastDialog = session.dialogStack().slice(-1)[0]; if (lastDialog && lastDialog.id === 'UserAdd') { // 已经在处理该对话框,忽略本次触发 next(); return; } // 使用beginDialog压栈启动子对话框,结束后回到原对话框 session.beginDialog('UserAdd', args); } });
为什么这样有效:
- 全局的
triggerAction确保用户在任意对话框中都能触发UserAdd; onSelectAction里的逻辑避免了重复添加相同的对话框实例;session.beginDialog()会将子对话框压入对话栈,而不是替换整个栈,所以子对话框结束后,原对话框会从中断处继续执行。
方案二:保留beginDialogAction,限制triggerAction的触发场景
如果你想保留根对话框的beginDialogAction,可以在triggerAction的逻辑中判断当前对话框是否为根对话框,避免重复触发:
// 根对话框 bot.dialog('/', [ function (session, args, next) { session.send('Starting root dialog'); }, function (session) { session.send('Ending root dialog.'); } ]).beginDialogAction('addUser', 'UserAdd', { matches: /^user add$/i }); // 用户添加子对话框 bot.dialog('UserAdd', [ function (session, args, next) { session.send('Adding user.'); session.endDialog(); } ]).triggerAction({ matches: /^user add$/i, onSelectAction: (session, args, next) => { // 获取当前栈顶的对话框 const currentDialog = session.dialogStack().slice(-1)[0]; // 如果当前在根对话框,由beginDialogAction处理,忽略triggerAction if (currentDialog.id === '/') { next(); return; } // 其他对话框中,压栈启动子对话框 session.beginDialog('UserAdd', args); } });
关键注意事项:
- 无论哪种方案,子对话框必须调用
session.endDialog()(或session.endDialogWithResult())来结束,否则父对话框永远不会恢复执行; - 避免给同一个匹配规则同时绑定
beginDialogAction和triggerAction,这是造成重复实例的根本原因。
内容的提问来源于stack exchange,提问作者gpsugy
相关产品推荐
相关产品推荐

