SignalR客户端不能在AngularJs控制器中工作
SignalR client doesn't work inside AngularJs controller
我创建了一个基于路由的Angular应用。不使用路由,Signalr工作得很好,但是当我使用路由时,Signalr只以一种方式工作-从客户端到服务器。
<html ng-app="SignalR">
<head>
//Scripts
<script src="~/signalr/hubs"></script>
</head>
<body>
<a href="#/Today">Today</a>
<a href="#/History">History</a>
<div ng-view>
</div>
<script type="text/javascript">
var hubConnetion = undefined;
hubConnetion = $.connection.hubs;
$.connection.hub.start();
var SignalRControllers = angular.module('SignalRControllers', []);
var SignalRApp = angular.module('SignalR', ['ngRoute', 'SignalRControllers']);
SignalRApp.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/Today', {
templateUrl: '@Url.Action("Today","Home")'
}).
when('/History', {
templateUrl: '@Url.Action("History", "Home")'
})
}]);
</script>
<script src="~/AngularJs/TodayController.js"></script>
</body>
</html>
TodayController.js
SignalRControllers.controller('TodayController', ['$scope', '$http',
function ($scope, $http) {
$scope.sendTask = function () {
hubConnetion.server.sendTask($("#taskName").val());//works
}
$scope.Task = "task1";
hubConnetion.client.getTask= function (Task) {//never invoked
$scope.Task = Task;
}
}]);
Today.html
<div ng-controller="TodayController">
<div>{{Task}}</div>
<input id="taskName" type="text" />
<div ng-click="sendTask()">SendTask</div>
</div>
Hubs.cs
public class Hubs: Hub
{
public void SendTask(string Name)
{
Clients.All.GetTask(Name);
}
}
我不确定,但我认为,因为 hubconnection 变量被包裹在控制器内,signlarR找不到它。有没有什么角魔法可以解决这个问题?
我也是SignalR的新手(也是Angular的第一次用户),所以我在ASP中重新创建(并简化)了这个项目。. NET MVC 4 (SignalR 2.2)来解决这个问题。而且我认为不止一个……
1) SignalR使用JQuery。在jQuery(以及几乎任何其他JS框架)中,最好在"document ready"事件之后执行代码。因此,我将SignalR设置包装在jQuery文档就绪处理程序中(参见下面的代码)。此外,我删除了hubConnetion
全局变量,因为全局变量是坏的+在jQuery文档准备处理程序包装后,变量是局部的处理程序,不能在控制器代码访问…
2) 主要问题是这个 (SignalR客户端API的一部分):
通常在调用start方法之前注册事件处理程序建立连接。如果你想注册一些事件处理程序,您可以这样做,但是您必须注册至少一个事件处理程序,然后才能调用start方法。这样做的一个原因是,在一个对象中可以有许多hub应用程序,但您不希望触发OnConnected事件每个集线器,如果你只使用其中一个。当连接建立后,Hub上存在客户端方法proxy告诉SignalR触发OnConnected事件。如果你在调用start方法之前不要注册任何事件处理程序将能够调用Hub上的方法,但是Hub的OnConnected方法将不会调用任何客户端方法服务器 .
事件处理程序是在控制器工厂方法中设置的,该方法比连接start()
方法要晚得多。尝试在调用start()
之前添加临时处理程序,如下所示:
$.connection.tasklistHub.client.getTask = function () { };
3)为了确保问题是在SignalR而不是Angular中,我已经打开了服务器端和客户端跟踪。在完成上述所有更改后,客户端成功接收到来自服务器的事件:
SignalR: Triggering client hub event 'getTask' on hub 'TasklistHub'
但是Angular无法用接收到的数据更新div。解决方案是使用本文中提到的$rootScope.$apply
函数来同时使用SignalR和Angular。现在一切都按预期进行。完整代码如下:
旁注:我知道这只是示例代码。在任何现实世界的项目中,我会考虑将SignalR中心包装在客户端上的某种服务中,如上面提到的文章或使用这个库(看起来非常优雅)
我也收回我之前关于客户端处理程序名称的回答,因为根据同一文档,客户端方法名称匹配是不区分大小写的…
Index.cshtml
<html lang="en" ng-app="SignalR">
<head>
<meta charset="utf-8" />
<title>SignalR & AngularJS</title>
<script src="~/Scripts/jquery-1.6.4.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
<script src="~/signalr/hubs"></script>
<script src="~/Scripts/angular.js"></script>
<script type="text/javascript">
$(function() {
$.connection.hub.logging = true;
// temporary handler to force SignalR to subscribe to server events
$.connection.tasklistHub.client.getTask = function () { };
$.connection.hub.start().done(function () {
$('#connectionStatus').text('Connected');
console.log('Now connected, connection ID =' + $.connection.hub.id);
});
});
var SignalRControllers = angular.module('SignalRControllers', []);
var SignalRApp = angular.module('SignalR', ['SignalRControllers']);
</script>
<script src="~/Scripts/app/TodayController.js"></script>
</head>
<body>
<div id="body">
<div ng-view>
<div ng-controller="TodayController">
<div id="connectionStatus"></div>
<div>{{Task}}</div>
<input id="taskName" type="text"/>
<input type="button" name="Send Task" value="Send Task" data-ng-click="sendTask()" />
</div>
</div>
</div>
</body>
</html>
TodayController.js
SignalRControllers.controller('TodayController', [
'$scope', '$http', '$rootScope',
function ($scope, $http, $rootScope) {
$scope.sendTask = function() {
$.connection.tasklistHub.server.sendTask($("#taskName").val());
};
$scope.Task = "Empty";
$.connection.tasklistHub.client.getTask = function (task) {
console.log(task);
$rootScope.$apply(function () {
$scope.Task = task;
});
};
}
]
);
你的解决方案是完美的,对于那些面对这个问题,即使在你的讲座之后,有一个简单的解决方案,从服务器到客户端在应用程序的每个部分的响应:
angular.module('groupApp').run(function ($rootScope, chat) {
$rootScope.messages = [];
chat.client.newMessage = function onNewMessage(message) {
$rootScope.messages.push({ message: message });
$rootScope.$apply();
};
});
在你的视图中,你可以在任何地方使用'messages'数组:
<div ng-repeat="m in messages">
{{m.message}}
</div>
我的问题
- 为什么ng控制器不调用或工作或功能不工作
- AngularJS控制器不工作,为什么?(简单的控制器示例)
- 角度控制器功能赢得'不按指令工作
- console.log在角度控制器内不工作
- 角度控制器功能不;在指令内部调用时,似乎无法始终如一地工作
- 如何使Angular JS控制器与指令一起工作
- AngularApp中的多个控制器不工作
- 具有范围变量的控制器不工作
- 角度指令和属性Don'在控制器内创建和设置时无法工作
- AngularJS控制器没有'第一次刷新页面后无法工作
- 包含ngMock时控制器不工作
- 部分html视图's控制器未使用KendoPanelBar内容URL在指令模板URL中工作
- 在第三个控制器中使用时RootScope不工作
- angularJS-当我添加ngRoute时,控制器停止工作
- ng-显示无法从控制器工作
- extjs setLoading()不能从控制器工作
- 如何让这个AngularJS控制器工作($scope变量没有在控制器中初始化)
- NodeJS Express req.params,enrouten控制器工作不正常
- 我如何使ui-router控制器工作
- $emit from子控制器工作,但是$broadcast from父控制器不起作用