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

SignalR 2.4.1使用onclose报错:Cannot read properties of undefined (reading 'onclose')

SignalR 2.4.1 处理浏览器关闭时的用户上下文清理问题

错误原因分析

你遇到的Cannot read properties of undefined (reading 'onclose')错误,是因为SignalR 2.x 客户端没有onclose方法——这个API是ASP.NET Core SignalR(即SignalR 3.0+版本)新增的,旧版2.4.1并不支持。

解决方案

1. 正确绑定SignalR断开连接事件

在SignalR 2.x中,需要使用disconnected方法来监听连接断开事件:

// 替换你原来的onclose代码,改用SignalR 2.x原生的断开事件绑定
SignalrConnection.disconnected(function() {
    console.log("SignalR连接已断开");
    // 这里可以处理断开后的基础逻辑,但注意:浏览器关闭时这个事件可能不会即时触发
});

2. 主动监听浏览器关闭事件,实时通知后端清理

浏览器/标签页关闭时,直接通过SignalR异步调用可能会被浏览器中断,推荐使用navigator.sendBeacon(专为页面卸载时发送请求设计,浏览器会确保请求完成),或者结合SignalR的主动调用:

客户端代码实现

// 监听浏览器卸载事件(关闭标签页/窗口)
window.addEventListener('beforeunload', function(event) {
    // 确保已获取到连接ID和公司ID
    if (mHubConnectionId && typeof companyid !== 'undefined') {
        // 方式1:使用sendBeacon调用后端API(推荐,可靠性更高)
        const formData = new FormData();
        formData.append('connectionId', mHubConnectionId);
        formData.append('companyId', companyid);
        navigator.sendBeacon('/api/Chat/CleanUserContext', formData);

        // 方式2:尝试SignalR主动调用(可能因浏览器中断请求而失败,仅作备选)
        // ChatProxy.invoke("CleanUserContext", mHubConnectionId)
        //     .fail(err => console.log("发送清理请求失败:", err));
    }
});

后端Hub与API实现

Hub中添加主动清理方法
public class CoolHub : Hub
{
    // 你的Connect方法保持不变
    public void Connect(int companyId)
    {
        // 将用户上下文(ConnectionId、CompanyId等)存入数据库
        // ... 你的业务代码
    }

    // 主动清理用户上下文的方法
    public void CleanUserContext(string connectionId)
    {
        // 根据ConnectionId从数据库删除对应的用户上下文
        // ... 你的业务代码
    }

    // 补充:SignalR自带的断开回调(处理未主动通知的场景,比如网络异常)
    public override Task OnDisconnected(bool stopCalled)
    {
        // stopCalled=true:客户端主动调用stop断开;false:连接意外断开(如浏览器关闭、网络中断)
        if (!stopCalled)
        {
            // 根据Context.ConnectionId清理数据库中的用户上下文
            // ... 你的业务代码
        }
        return base.OnDisconnected(stopCalled);
    }
}
可选:后端API接口(配合sendBeacon使用)

如果使用sendBeacon,需要添加对应的API控制器:

[Route("api/[controller]")]
public class ChatController : Controller
{
    private readonly YourDbContext _dbContext;

    public ChatController(YourDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    [HttpPost("CleanUserContext")]
    public IActionResult CleanUserContext(string connectionId, int companyId)
    {
        // 根据connectionId和companyId删除数据库中的用户上下文
        var userContext = _dbContext.UserContexts.FirstOrDefault(u => u.ConnectionId == connectionId && u.CompanyId == companyId);
        if (userContext != null)
        {
            _dbContext.UserContexts.Remove(userContext);
            _dbContext.SaveChanges();
        }
        return Ok();
    }
}

关键注意事项

  • navigator.sendBeacon仅支持POST请求,且数据格式限制为FormData、Blob等,不能直接发送JSON(如需JSON可转为Blob)。
  • SignalR的OnDisconnected方法会在连接超时后触发(默认30秒),可以作为主动通知的兜底方案,确保用户上下文最终被清理。
  • 确保mHubConnectionId和companyid在beforeunload事件作用域内可访问(比如声明为全局变量或通过闭包传递)。

内容的提问来源于stack exchange,提问作者Sana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 16:43:24