如何结合Promises使用Autobahn.js?解决调用偶发中断问题
Autobahn连接偶发中断及复用问题
我正在使用依赖Autobahn的服务,但调用过程中出现偶发中断情况。以下是我的代码实现:
import autobahn from 'autobahn'; var connection = new autobahn.Connection({ url: 'ws://host.docker.internal:8080/service', realm: 'realm1', protocols: ['wamp.2.json'] }); //Attempt 1 - 一开始就打开连接复用,但createObject里的日志没触发 connection.open(); connection.onopen = async function (session) { console.log('Connection established'); } connection.onclose = function (reason) { if (reason !== 'lost') { console.log("Connection closed. Reason: " + reason); } }; function createObject(obj) { return new Promise((resolve, reject) => { // Attempt 2 - 尝试在方法内打开连接,但多次调用时服务交互异常 connection.onopen = async function (session) { console.log('Creating new object'); session.call('service.object.create', [], obj).then( function (res) { resolve(); }, function (error) { console.log(error); reject(error) } ) } }) } export { createObject }
我还有delete、search等共4个类似createObject的服务交互方法。
我尝试在文件开头打开连接以复用,但createObject方法中的console.log('Creating new object')并未触发;也尝试每次调用方法时开关连接,却导致事件丢失。
编辑
我尝试了以下方法,看似有效但感觉不够规范,请问这是正确的做法吗?
var session connection.open(); connection.onopen = async function (ses) { session = ses // 原代码笔误为session.ses console.log('Connection established'); }
问题分析与解决方案
原代码核心问题
- Attempt 1的问题:你先调用
connection.open()再赋值onopen回调,若连接快速建立完成,这个回调不会触发。同时createObject里重新覆盖了onopen回调,原初始化逻辑被覆盖;若连接已处于打开状态,新的onopen不会自动执行,导致Creating new object日志没触发。 - Attempt 2的问题:每次调用
createObject都覆盖onopen回调,多次调用时后续回调会覆盖前一次的,导致之前的Promise无法正确resolve/reject,出现事件丢失或交互异常。
正确实现方式
应确保连接仅初始化一次,打开后保存session实例供所有服务方法复用,同时处理连接断开后的重连逻辑,避免偶发中断影响调用。
示例代码:
import autobahn from 'autobahn'; // 初始化连接 const connection = new autobahn.Connection({ url: 'ws://host.docker.internal:8080/service', realm: 'realm1', protocols: ['wamp.2.json'] }); let sessionInstance = null; // 用Promise封装连接初始化,确保调用服务时能等待连接就绪 const connectionPromise = new Promise((resolve, reject) => { connection.onopen = (session) => { console.log('Connection established'); sessionInstance = session; resolve(session); }; connection.onclose = (reason, details) => { sessionInstance = null; if (reason !== 'lost') { console.log("Connection closed. Reason: " + reason); reject(new Error(`Connection closed: ${reason}`)); } else { // Autobahn默认支持重连,这里添加重连日志 console.log('Connection lost, attempting to reconnect...'); } }; connection.open(); }); // 通用服务调用封装,自动处理session有效性 async function callService(procedure, args = [], kwargs = {}) { if (!sessionInstance) { // 未就绪则等待连接完成 await connectionPromise; } try { return await sessionInstance.call(procedure, args, kwargs); } catch (error) { console.error(`Service call failed for ${procedure}:`, error); throw error; } } // 具体业务方法 async function createObject(obj) { console.log('Creating new object'); await callService('service.object.create', [], obj); } async function deleteObject(id) { console.log('Deleting object'); await callService('service.object.delete', [id]); } async function searchObjects(query) { console.log('Searching objects'); return await callService('service.object.search', [], query); } export { createObject, deleteObject, searchObjects };
你编辑中代码的评价
修正笔误(session.ses改为session = ses)后,这个思路方向是对的——保存全局session实例供后续调用,但缺少关键环节:
- 未处理连接未就绪时的等待逻辑,若在连接建立前调用服务会因
session为null报错 - 未处理连接断开后的重连与session重置,偶发中断后无法自动恢复服务调用
- 未封装通用调用逻辑,每个业务方法需重复检查session有效性
所以这个思路可行,但不够完整规范,建议按上面的完整实现优化。
内容的提问来源于stack exchange,提问作者Ando
相关产品推荐
相关产品推荐

