jQuery SignalR 客户端 .off() 函数仅删除最后注册的回调

Jer*_*984 0 javascript asp.net signalr angularjs signalr.client

我在我的应用程序中使用 SignalR 以允许我的 ASP.NET 服务器应用程序将数据推送到我的 Angular SPA Web 客户端。在 Web 应用程序中,我包含了 jquery.signalR-2.2.0.js 文件。我不在 http(s)://serverurl/signalr/hubs 上使用自动生成的代理。

Web 应用程序有多个可重用的小部件(指令),每个小部件都有自己独立的作用域。同一小部件​​/指令的多个实例需要注册一个可由服务器的 SignalR 集线器执行的回调,因此我有一个这样的功能:

 var on = function (eventName, callback) {
            proxy.on(eventName, callback);
          };
Run Code Online (Sandbox Code Playgroud)

这个函数在一个单独的服务中,它也有连接和代理对象,直到现在一切正常......

从一个负责小部件实例的角度控制器,上面的函数被调用如下:

var callback = function (){
     console.log('Callback fired on controller with Id' + $scope.id)
}

proxyHub.on('myEvent',callback);
Run Code Online (Sandbox Code Playgroud)

控制器处于隔离范围内,因此 var 回调是每个控制器的不同对象。

我能够为来自不同控制器的同一事件注册多个回调,并且一切仍然按预期工作。

现在我需要从控制器实例取消注册回调,所以我在我的单独服务中有以下方法:

 var off = function(eventName,callback) {
            proxy.off(eventName,callback);
        };
Run Code Online (Sandbox Code Playgroud)

这是从特定的控制器实例调用的,如下所示:

//callback is exactly the same variable as used in the .on function for this controller   
hubProxy.off('myevent',callback);
Run Code Online (Sandbox Code Playgroud)

麻烦来了:只有最后注册的回调会从事件中删除。所有其他注册的回调仍然被调用。如果我再次尝试调用 .off 函数,则什么也不会发生,并且我无法取消注册其他回调。

主要问题是:如何从事件中取消注册特定回调???

Ily*_*nin 5

来自集线器源代码来看,似乎不可能从单个事件中取消订阅多个重复的回调。

这是on源代码中的函数:

on: function (eventName, callback) {
        /// <summary>Wires up a callback to be invoked when a invocation request is received from the server hub.</summary>
        /// <param name="eventName" type="String">The name of the hub event to register the callback for.</param>
        /// <param name="callback" type="Function">The callback to be invoked.</param>
        var that = this,
            callbackMap = that._.callbackMap;

        // Normalize the event name to lowercase
        eventName = eventName.toLowerCase();

        // If there is not an event registered for this callback yet we want to create its event space in the callback map.
        if (!callbackMap[eventName]) {
            callbackMap[eventName] = {};
        }

        // Map the callback to our encompassed function
        callbackMap[eventName][callback] = function (e, data) {
            callback.apply(that, data);
        };

        $(that).bind(makeEventName(eventName), callbackMap[eventName][callback]);

        return that;
    },
Run Code Online (Sandbox Code Playgroud)

如您所见,“事件:回调”对已保存callbackMap并绑定到集线器。如果多次调用,callbackMap将被相同的值覆盖,但回调将被多次绑定。

off函数中:

off: function (eventName, callback) {
        /// <summary>Removes the callback invocation request from the server hub for the given event name.</summary>
        /// <param name="eventName" type="String">The name of the hub event to unregister the callback for.</param>
        /// <param name="callback" type="Function">The callback to be invoked.</param>
        var that = this,
            callbackMap = that._.callbackMap,
            callbackSpace;

        // Normalize the event name to lowercase
        eventName = eventName.toLowerCase();

        callbackSpace = callbackMap[eventName];

        // Verify that there is an event space to unbind
        if (callbackSpace) {
            // Only unbind if there's an event bound with eventName and a callback with the specified callback
            if (callbackSpace[callback]) {
                $(that).unbind(makeEventName(eventName), callbackSpace[callback]);

                // Remove the callback from the callback map
                delete callbackSpace[callback];

                // Check if there are any members left on the event, if not we need to destroy it.
                if (!hasMembers(callbackSpace)) {
                    delete callbackMap[eventName];
                }
            } else if (!callback) { // Check if we're removing the whole event and we didn't error because of an invalid callback
                $(that).unbind(makeEventName(eventName));

                delete callbackMap[eventName];
            }
        }

        return that;
    },
Run Code Online (Sandbox Code Playgroud)

该“事件:回调”对从函数的callbackMap第一次调用中删除,off并从集线器(一次)解除绑定。但是在下一次调用时,“事件:回调”对不再存在,因此所有其他事件仍然绑定到集线器。

一种解决方案可能是从事件中删除所有回调,只需off使用 only调用函数myEventName,而不指定回调。但我不确定,这是否适用于您的情况。