You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合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');
}

问题分析与解决方案

原代码核心问题

  1. Attempt 1的问题:你先调用connection.open()再赋值onopen回调,若连接快速建立完成,这个回调不会触发。同时createObject里重新覆盖了onopen回调,原初始化逻辑被覆盖;若连接已处于打开状态,新的onopen不会自动执行,导致Creating new object日志没触发。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:25:35