My AngularJS application with CRUD functionality relies on a WebSocket server for processing information. This eliminates the need for constant HTTP polling and allows updates to be automatically pushed to all users.
When setting up my services, I quickly realized that traditional HTTP service structures wouldn't work. Instead of creating separate services for each model, I had to explore other options due to the nature of WebSocket connections. I considered two solutions:
1) Create a single service that establishes the connection and share it with other services for specific queries.
2) Develop a type-agnostic service that can be used by all controllers needing access to the connection and data.
Option 2 seemed more manageable and reusable, so I implemented it. This approach presented an opportunity to create a master `data` object instead of explicitly defining models for each type of data. The `data` object dynamically generates child objects under `myService.data` as needed when new data is received. This design allows for server-side model updates to be seamlessly reflected on the client side, requiring only a controller to handle the updated data.
However, this approach posed a challenge. Since `myService.Data` is initially an empty object without child objects, scopes trying to access future children must reference the object itself. For instance, using `$scope.user = myService.data.user` at the beginning throws an error because the object doesn't exist during declaration. It seems that each controller must have `$scope.data = myservice.data`, with the view using `
My question revolves around finding a balance between dynamic data model updates within the service and controllers accessing only the necessary data portions. Initially feeling clever about the design, I now see that all controllers will have access to the entire data model, raising doubts about its efficiency.
Below is my WebSocket service implementation:
app.factory('WebSocketService', ['$rootScope', function ($rootScope) {
var factory = {
socket: null,
data: {},
startConnection: function () {
// WebSocket initialization
socket = new WebSocket('ws://localhost:2012/')
socket.onopen = function () {
// Actions on open
}
socket.onclose = function () {
// Actions on close
}
socket.onmessage = function (event) {
var packet = JSON.parse(event.data);
// Packet model:
// packet.Data: Serialized object containing data
// packet.Operation: Data operation
// packet.Model: Child object in Factory.data to use
// packet.Property: Property used for update and delete operations
// Deserialize data
packet.Data = JSON.parse(packet.Data);
// Handle different operations
if (packet.Operation == "Refresh") {
factory.data[packet.Model] = packet.Data
}
// Other operations
$rootScope.$digest();
}
},
stopConnection: function () {
if (socket) {
socket.close();
}
},
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
}]);
Here is a simple controller accessing user information and initiating the WebSocket connection:
App.controller("AuthenticationController", function ($scope, WebSocketService) {
init();
function init() {
WebSocketService.startConnection();
}
// Only way to access service data
$scope.data = WebSocketService.data
});
HTML utilizing the controller:
<div data-ng-controller="AuthenticationController">
<span data-ng-model="data">{{data.user.userName}}</span>
</div>