在SignalR中使用Angular时,当服务中的对象发生更改时,如何通知控制器

When using Angular with SignalR, how do I notify a controller when a change is made to an object in a service?

本文关键字:何通知 控制器 通知 对象 SignalR Angular 服务      更新时间:2023-09-26

我有一个相当简单的Angular应用程序,有四个控制器和两个服务。一个服务存储数据并与其他控制器共享,类似于以下内容:

var DataService = function($http) {
    this.testData = [];
}    
MyApp.service('DataService', ["$http", DataService]);

另一个服务包含客户端SignalR方法,类似于以下内容:

var HubService = function(DataService) {    
    this.testHub = $.connection.TestHub;
    this.connectionStatus = [];
    this.connectToHub = function(callback) {
        var self = this;
        $.connection.hub.start().done(function() {
            self.connectionStatus.push(1);
            if (callback) {
                callback();
            }
        });
    };  
    this.getSomeData = function (node, callback) {        
        this.testHub.server.getSomeData(node).done(function (response) {            
            if (callback) { callback(); }         
        });
    };  
    this.testHub.client.addData = function(serverData) {
        DataService.testData.push(serverData)   
    };  
}
MyApp.service('HubService', ["DataService", HubService]);

其中服务器端集线器方法类似于

public class TestHub : Hub {
     public void GetSomeData(Node node) {
        var data = _queries.getSomeDataFromAServer();
        Clients.All.addData(data);
     }
}

现在一切都很好,我将DataService和HubService注入控制器中,我可以调用HubService.getSomeData()方法,该方法调用服务器端方法,然后调用客户端SignalR方法,DataService.testData对象就会更新。

问题是,直到下一个$digest周期(通常是某种UI事件),控制器才会收到此更改的通知。我需要立即通知管制员。我知道通常我可以调用$scope$apply()手动触发$digest循环,但由于服务方法是直接从服务器端方法调用的,因此无法使用$scope。

我该怎么办?如何使Angular监视服务对象以了解来自另一个服务的更改,或者如何在服务方法的所有控制器上触发$digest循环?

这可能不是答案,但您可以了解如何实现它的机制。

var app = angular.module('plunker', []);
app.service('myService', function($rootScope) {
  var data = 0;
  var id = 0;
  var increment = function() {
    data = data + 1;
    $rootScope.$apply();
    console.log("Incrementing data", data);
  };
  this.start = function() {
    id = setInterval(increment, 500) ;
  };
  this.stop = function() {
    clearInterval(id);
  };
  this.getData = function() { return data; };
}).controller('MainCtrl', function($scope, myService) {
  $scope.service = myService;
  $scope.controllerData = 0;
  $scope.start = function() {
    myService.start();
  };
  $scope.stop = function() {
    myService.stop();
  };
  $scope.$watch('service.getData()', function(newVal) {
    console.log("New Data", newVal);
    $scope.controllerData = newVal;
  });
});