BotFramework报错:Cannot perform 'get' on a proxy that has been revoked 求助
解决MS Teams机器人
Cannot perform 'get' on a proxy that has been revoked错误 我正在开发一款可按模块向学生发送内容的MS Teams机器人,目前拆分了三个核心文件:
methods.js:封装发送文本、附件等所有消息发送方法teamBot.js:捕获用户发送的特定关键词,触发对应业务逻辑test.js:对接Airtable获取内容,调用发送方法推送
现在遇到Cannot perform 'get' on a proxy that has been revoked错误,推测是context的传递方式有问题。目前我是通过参数直接传递context,感觉这种方式不正确,想请教如何正确实现跨文件功能并保留context的有效性?
现有代码
teamsBot.js
const test = require("./test"); class TeamsBot extends TeamsActivityHandler { constructor() { super(); // 记录点赞数 this.likeCountObj = { likeCount: 0 }; this.onMessage(async (context, next) => { console.log("Running with Message Activity."); let txt = context.activity.text; // const removedMentionText = TurnContext.removeRecipientMention(context.activity); // if (removedMentionText) { // // 移除换行符 // txt = removedMentionText.toLowerCase().replace(/\n|\r/g, "").trim(); // } // 根据IM文本触发命令 switch (txt) { case "Begin": { await test.sendModuleContent(context) } } // 调用next()确保后续BotHandler执行 await next(); }); // 监听MembersAdded事件 this.onMembersAdded(async (context, next) => { const membersAdded = context.activity.membersAdded; for (let cnt = 0; cnt < membersAdded.length; cnt++) { if (membersAdded[cnt].id) { const card = cardTools.AdaptiveCards.declareWithoutData(rawWelcomeCard).render(); await context.sendActivity({ attachments: [CardFactory.adaptiveCard(card)] }); break; } } await next(); }); } }
test.js
const ms = require('./methods') async function sendModuleContent(context) { data = module_text // 从Airtable获取的内容 await ms.sendText(context, data) }
methods.js
const {TeamsActivityHandler, ActivityHandler, MessageFactory } = require('botbuilder'); async function sendText(context, text){ console.log("Sending text") await context.sendActivity(text); }
问题原因与解决方案
错误原因
这个错误是因为Bot Framework中的context是一个代理对象,当前对话回合(turn)结束后,框架会自动回收这个代理、释放资源。如果在异步操作(比如从Airtable拉取数据)完成后再使用原context,代理已经被撤销,就会触发该错误。
正确实现方式
方案1:克隆Context保留有效引用
在传递context前,用TurnContext.clone创建副本,确保异步操作完成后仍能正常使用:
// teamsBot.js中引入TurnContext const { TurnContext } = require('botbuilder'); // 修改Begin分支的调用逻辑 case "Begin": { const clonedContext = TurnContext.clone(context); await test.sendModuleContent(clonedContext) }
方案2:提取核心信息,避免传递完整Context
不直接传递整个context,而是提取发送消息必需的对话引用和适配器,手动构建消息发送逻辑:
- 更新teamsBot.js的调用:
case "Begin": { const conversationReference = TurnContext.getConversationReference(context.activity); await test.sendModuleContent(conversationReference, this.adapter) }
- 修改test.js:
const ms = require('./methods') async function sendModuleContent(conversationReference, adapter) { const data = module_text; // 从Airtable获取内容 await ms.sendText(conversationReference, adapter, data) }
- 调整methods.js:
async function sendText(conversationReference, adapter, text){ console.log("Sending text"); await adapter.continueConversation(conversationReference, async (context) => { await context.sendActivity(text); }); }
方案3:确保异步操作在当前Turn内完成
检查Airtable数据获取逻辑是否存在不必要的延迟,确保所有异步操作在onMessage的next()调用前完成(你的代码已经用await等待sendModuleContent,但克隆Context仍是更稳妥的做法)。
额外优化建议
- 尽量避免跨文件传递
context,通过提取必要参数的方式解耦代码 - 所有异步操作必须用
await确保执行顺序 - 在
test.js中添加错误捕获,避免Airtable请求失败导致Bot流程中断
内容的提问来源于stack exchange,提问作者Dummy Cron
相关产品推荐
相关产品推荐

