Javascript 如果我将所有数据提供给所有控制器,我会遇到什么问题?

Javascript 如果我将所有数据提供给所有控制器,我会遇到什么问题?,javascript,angularjs,angularjs-service,angularjs-controller,Javascript,Angularjs,Angularjs Service,Angularjs Controller,我的AngularJS CRUD应用程序通过WebSocket服务器处理信息。(这主要是为了让一个用户的更新自动推送到所有用户,而无需进行大规模HTTP轮询) 我很早就意识到,我必须以与通常使用HTTP服务不同的方式设置我的服务。通常,对于我正在使用的每个模型,我会为它们提供自己的服务来填充特定的模型。但是,这对于Websocket连接是不可行的,因为我不希望每个服务都有单独的连接。因此,有两种解决方案 1) 设置建立连接的单个服务,然后与将使用该服务进行特定查询的其他服务共享该连接 2) 创建

我的AngularJS CRUD应用程序通过WebSocket服务器处理信息。(这主要是为了让一个用户的更新自动推送到所有用户,而无需进行大规模HTTP轮询)

我很早就意识到,我必须以与通常使用HTTP服务不同的方式设置我的服务。通常,对于我正在使用的每个模型,我会为它们提供自己的服务来填充特定的模型。但是,这对于Websocket连接是不可行的,因为我不希望每个服务都有单独的连接。因此,有两种解决方案

1) 设置建立连接的单个服务,然后与将使用该服务进行特定查询的其他服务共享该连接

2) 创建一个单一的类型无关服务,所有需要访问连接和数据的控制器都将使用该服务

选项2似乎更易于管理,并且可以跨应用程序重用,所以我开始使用它。那时我才意识到这其实是一个机会。我可以创建一个主
data
对象,并在数据从请求流入时根据需要动态创建
myService.data
的子对象,而不是为客户端可以接收的每种类型的数据显式创建模型。因此,如果我需要更新我的模型,我只需要在服务器级别更新模型,客户机已经知道如何接收它;它只需要一个知道如何使用它的控制器

然而,这个机会带来了一个缺点。显然,因为
myService.Data
在创建时是一个空的、无子对象,任何想要引用其未来子对象的作用域都必须简单地引用对象本身

例如,
$scope.user=myService.data.user
抛出一个错误,因为该对象在声明中不存在。似乎我唯一的选择是每个控制器只需使用
$scope.data=myservice.data
,每个控制器的视图只需使用
,声明类似于
{{data.user.username}
。我已经测试过了,这确实有效

我的问题是,;有什么办法可以让我两全其美?我可以让我的服务动态更新它的数据模型,但我的控制器仍然只能访问他们需要的部分吗?我我觉得自己很聪明,直到我意识到我所有的控制器都可以访问整个数据模型。。。但我真的不能确定这是否是一个大问题

这是我的服务:

app.factory('WebSocketService', ['$rootScope', function ($rootScope) {
    var factory = {
        socket: null,
        data: {},
        startConnection: function () {
            //initialize Websocket
            socket = new WebSocket('ws://localhost:2012/')
            socket.onopen = function () {
              //todo: Does anything need to happen OnOpen?
            }
            socket.onclose = function () {
              //todo: Does anything need to happen OnClose?
            }
            socket.onmessage = function (event) {
                var packet = JSON.parse(event.data);
                ////Model of Packet:
                ////packet.Data: A serialised Object that contains the needed data
                ////packet.Operation: What to do with the Data
                ////packet.Model: which child object of Factory.data to use
                ////packet.Property: used by Update and Delete to find a specific object with a property who's name matches this string, and who's value matches Packet.data
                //Deserialize Data
                packet.Data = JSON.parse(packet.Data);
                //"Refresh" is used to completely reload the array 
                // of objects being stored in factory.data[packet.Model]
                // Used for GetAll commands and manual user refreshes
                if (packet.Operation == "Refresh") {
                    factory.data[packet.Model] = packet.Data
                }
                //Push is used to Add an object to an existing array of objects.  
                //The server will send this after somebody sends a successful POST command to the WebSocket Server
                if (packet.Operation == "Push") {
                    factory.data[packet.Model].push(packet.Data)
                }
                if (packet.Operation == "Splice") {
                    for (var i = 0; i < factory.data[packet.Model].length; i++) {
                        for (var j = 0; j < packet.Data.length; j++){
                            if (factory.data[packet.Model][i][packet.Property] == packet.Data[j][packet.Property]) {
                                factory.data[packet.Model].splice(i, 1);
                                i--;
                            }
                        }
                    }          
                }
                // Used to update existing objects within the Array.  Packet.Data will be an array, although in most cases it will usually only have one value.  
                if (packet.Operation == "Update") {
                    for (var i = 0; i < factory.data[packet.Model].length; i++) {
                        for (var j = 0; j < packet.Data.length; j++) {
                            if (factory.data[packet.Model][i][packet.Property] == packet.Data[j][packet.Property]) {
                                factory.data[packet.Model][i] = packet.Data[j]
                                i--;
                            }
                        }
                    }
                }
                //Sent by WebSocket Server after it has properly authenticated the user, sending the user information that it has found.  
                if (packet.Operation == "Authentication") {
                    if (packet.Data == null) {
                        //todo: Authentication Failed.  Alert User Somehow
                    }
                    else {
                        factory.data.user = packet.Data;
                        factory.data.isAuthenticated = true;
                    }

                }
                $rootScope.$digest();
            }  
        },
        stopConnection: function () {
            if (socket) {
                socket.close();
            }
        },
        //sends a serialised command to the Websocket Server according to it's API.
        //The DataObject must be serialised as a string before it can be placed into Packet object,which will also be serialised.  
        //This is because the Backend Framework is C#, which must see what Controller and Operation to use before it knows how to properly Deserialise the DataObject.
        sendPacket: function (Controller, Operation, DataObject) {
            if (typeof Controller == "string" && typeof Operation == "string") {
                var Data = JSON.stringify(DataObject);
                var Packet = { Controller: Controller, Operation: Operation, Data: Data };
                var PacketString = JSON.stringify(Packet);
                socket.send(PacketString);
            }
        }
    }
    return factory
}]);
下面是使用该控制器的HTML

    <div data-ng-controller="AuthenticationController">
        <span data-ng-model="data">{{data.user.userName}}</span>
    </div>

{{data.user.userName}

您可以做的一件事是将
数据
对象存储在根作用域上,并在各种控制器上设置监视,以监视它们需要的任何特定于控制器的键:

// The modules `run` function is called once the 
// injector is finished loading all its modules.
App.run(function($rootScope, WebSocketService) {
  WebSocketService.startConnection();
  $rootScope.socketData = WebSocketService.data;
});

// Set up a $watch in your controller
App.controller("AuthenticationController", function($scope) {
  $scope.$watch('socketData.user', function(newUser, oldUser) {
    // Assign the user when it becomes available.
    $scope.user = newUser;
  });
});

Promises(
$q
)可能是设置动态更新的最佳选择。我需要看更多的代码,给你一个大概的样子。哦,好的。我没有多少处理自定义承诺的经验,所以我现在就用一些代码更新问题。用代码和注释更新问题。我非常感谢你的意见!我实现了这个,它工作得非常好。它使我的部分变得越来越清晰,因为它们可以拥有“数据”以外的模型。我要等一天,看看是否有人能想出更好的办法,然后把这个作为答案。
// The modules `run` function is called once the 
// injector is finished loading all its modules.
App.run(function($rootScope, WebSocketService) {
  WebSocketService.startConnection();
  $rootScope.socketData = WebSocketService.data;
});

// Set up a $watch in your controller
App.controller("AuthenticationController", function($scope) {
  $scope.$watch('socketData.user', function(newUser, oldUser) {
    // Assign the user when it becomes available.
    $scope.user = newUser;
  });
});