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

AngularJS 1.x Socket.IO工厂注入:事件收发及连接检查问题

解决AngularJS Socket工厂未检查连接状态导致的异常问题

我明白你遇到的痛点——直接调用socket.emit时,如果Socket.IO连接还没建立或者已经断开,肯定会抛出异常,搞崩应用的稳定性。咱们可以通过改造现有的socket工厂,添加连接状态跟踪和安全发送逻辑来彻底解决这个问题。

改造后的Socket工厂

我们在工厂里维护连接状态,监听Socket.IO的连接/断开事件更新状态,同时在emit方法里先做连接检查,甚至可以缓存未发送的事件,等连接恢复后自动补发:

angularApp.factory('socket', function ($rootScope) {
    var socket = io();
    var isConnected = false;
    // 缓存未发送的事件,连接恢复后自动发送
    var pendingEvents = [];

    // 监听连接建立事件
    socket.on('connect', function() {
        isConnected = true;
        $rootScope.$apply();
        // 连接恢复后批量发送缓存的事件
        pendingEvents.forEach(function(event) {
            socket.emit(event.eventName, event.data, event.callback);
        });
        pendingEvents = [];
    });

    // 监听连接断开事件
    socket.on('disconnect', function() {
        isConnected = false;
        $rootScope.$apply();
    });

    return {
        // 暴露连接状态给控制器调用
        isConnected: function() {
            return isConnected;
        },
        on: function (eventName, callback) {
            socket.on(eventName, function () {
                var args = arguments;
                $rootScope.$apply(function () {
                    callback.apply(socket, args);
                });
            });
        },
        emit: function (eventName, data, callback) {
            if (isConnected) {
                socket.emit(eventName, data, function () {
                    var args = arguments;
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback.apply(socket, args);
                        }
                    });
                });
            } else {
                // 未连接时缓存事件
                pendingEvents.push({
                    eventName: eventName,
                    data: data,
                    callback: callback
                });
                // 可选:通过回调通知调用者当前未连接
                if (callback) {
                    $rootScope.$apply(function() {
                        callback(new Error('Socket未连接,请求已加入缓存'));
                    });
                }
            }
        }
    };
});

控制器中的使用方式

现在你可以放心调用emit,工厂会自动处理连接状态;如果需要给用户做即时提示,也可以手动检查连接状态:

$scope.$on('beginDataTransfer', function() {
    if (socket.isConnected()) {
        socket.emit('dataTransfer', "SOME DATA", function(err) {
            if (err) {
                console.error('数据发送失败:', err);
                // 这里可以给用户显示错误提示
            }
        });
    } else {
        console.log('Socket未连接,请求已缓存,将在连接恢复后发送');
        // 也可以在这里给用户弹出提示框
    }
});

关键改进点

  • 实时连接状态跟踪:通过监听Socket.IO的connect/disconnect事件,精准同步连接状态到Angular作用域
  • 事件缓存补发:避免未连接时丢失请求,连接恢复后自动补发缓存的事件
  • 友好的错误回调:给调用者提供错误反馈,方便做前端提示或异常处理
  • Angular作用域同步:所有状态变化都通过$rootScope.$apply()同步到Angular消化周期,确保视图能及时响应连接状态变化

这样改造后,再也不用担心因为Socket未连接触发异常了,还能提升应用的健壮性和用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:11:07