如何让SignalR invoke恢复代码优先于消息处理器执行?
解决方案
要让invoke调用完成后的恢复代码优先于消息处理器执行,核心思路是暂时缓存推送的消息,待invoke恢复逻辑执行完毕后再处理缓存的消息。具体实现步骤如下:
1. 新增状态标记与消息缓存队列
在你的类中添加两个变量,用于跟踪invoke状态和缓存待处理消息:
// 标记是否有invoke请求处于等待状态 #isInvokePending = false; // 缓存待处理的GameDataUpdate消息 #pendingGameUpdates: GameDataUpdate[] = [];
2. 修改消息处理器逻辑
原消息处理器不再直接处理消息,而是根据#isInvokePending状态决定缓存或立即处理:
this.connection.on("GameDataUpdatedV1", async (evt: GameDataUpdatedEvent) => { if (this.#isInvokePending) { // 若有invoke在等待,先缓存消息 this.#pendingGameUpdates.push(evt.updateData); } else { // 无invoke等待时,正常处理消息 await this.#handleGameDataUpdate(evt.updateData); } });
3. 调整invoke调用流程
在调用invoke前标记状态,调用完成后先执行恢复代码,再批量处理缓存的消息:
console.log("About to invoke..."); this.#isInvokePending = true; try { await this.connection.invoke("TestInvoke", { testData: 123 }); // 优先执行invoke恢复逻辑 console.log("Resumed from invoke."); } finally { this.#isInvokePending = false; // 批量处理缓存的消息 for (const update of this.#pendingGameUpdates) { await this.#handleGameDataUpdate(update); } // 清空缓存队列 this.#pendingGameUpdates = []; }
原理说明
SignalR的消息推送处理器和invoke的回调逻辑都运行在JavaScript的同一个事件循环队列中。当invoke处于等待状态时,服务器推送的消息会不断进入事件队列并被依次执行,导致处理器输出先于invoke恢复代码。通过手动缓存消息并延迟处理,我们可以确保invoke完成后的逻辑优先执行,再统一处理期间积累的推送消息。
内容的提问来源于stack exchange,提问作者Jez
相关产品推荐
相关产品推荐

