我在我的应用程序中使用SignalR来允许我的ASP.NET Server应用程序将数据推送到我的Angular SPA Web客户端。 在Web应用程序中,我已经包含了jquery.signalR-2.2.0.js文件。我不在http(s)上使用自动生成的代理:// serverurl / signalr / hubs。
Web应用程序具有多个可重用的小部件(指令),每个小部件都有自己的独立范围。同一个小部件/指令的多个实例需要注册一个可以由服务器的SignalR Hub执行的回调,所以我有这样的函数:
var on = function (eventName, callback) {
proxy.on(eventName, callback);
};
这个函数是一个单独的服务,它也有连接和代理对象,到现在为止一切正常......
从一个角度控制器,负责一个小部件实例,上面的函数被调用如下:
var callback = function (){
console.log('Callback fired on controller with Id' + $scope.id)
}
proxyHub.on('myEvent',callback);
控制器处于隔离范围内,因此var回调是每个控制器的不同对象。
我能够从不同的控制器为同一个事件注册多个回调,并且一切仍然按预期工作。
现在我需要取消注册来自控制器实例的回调,所以我在单独的服务中有以下方法:
var off = function(eventName,callback) {
proxy.off(eventName,callback);
};
从特定的控制器实例中调用它,如下所示:
//callback is exactly the same variable as used in the .on function for this controller
hubProxy.off('myevent',callback);
出现问题:仅从事件中删除最后一次注册的回调。所有其他已注册的回调仍然被调用。如果我再次尝试调用.off函数,则没有任何反应,我无法取消注册其他回调。
主要问题是:如何从事件中取消注册特定的回调?
答案 0 :(得分:4)
从hubs source code开始,似乎无法从单个事件中取消订阅多个重复的回调。
这是来自源代码的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;
},
如您所见,“event:callback”对保存到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;
},
首次调用callbackMap
函数时从off
删除“event:callback”对,并从hub(一次)解除绑定。但是在下一次调用时,“event:callback”对不再存在,所以所有其他事件仍然绑定到hub。
一种解决方案可能是从事件中删除所有回调,只需调用仅off
的{{1}}函数,而不指定回调。但我不确定,如果这适用于您的情况。