Estoy empezando a familiarizarme con AngularJS, pero me gustaría crear una aplicación web que tenga una vista que se actualice automáticamente en tiempo real (sin actualización) para el usuario cuando algo cambia en la base de datos del lado del servidor.
¿Puede AngularJS manejar esto (en su mayoría) automáticamente para mí? Y si es así, ¿cuál es el mecanismo básico en funcionamiento?
Por ejemplo, ¿de alguna manera configura AngularJS para sondear la base de datos regularmente en busca de cambios en el "modelo"? ¿O usar algún tipo de mecanismo similar a Comet para notificar al código del lado del cliente de AngularJS que el modelo ha cambiado?
En mi aplicación, el desafío es que otro software del lado del servidor (no web) actualizará la base de datos en ocasiones. Pero esta pregunta se aplica igualmente a las aplicaciones web puras en las que es posible que varios clientes cambien la base de datos a través de los clientes web de AngularJS, y cada uno de ellos debe actualizarse cuando uno de ellos realiza un cambio en la base de datos (modelo).
fuente
Respuestas:
Tienes algunas opciones ...
Puede hacer un sondeo cada X milisegundos usando
$timeout
y$http
, o si los datos que está usando están conectados a un servicio REST, podría usar en$resource
lugar de$http
.Puede crear un servicio que use alguna implementación de Websocket y se use
scope.$apply
para manejar los cambios que empuja el socket. Aquí hay un ejemplo usando socket.io, una biblioteca websocket de node.js:myApp.factory('Socket', function($rootScope) { var socket = io.connect('http://localhost:3000'); //Override socket.on to $apply the changes to angular return { on: function(eventName, fn) { socket.on(eventName, function(data) { $rootScope.$apply(function() { fn(data); }); }); }, emit: socket.emit }; }) function MyCtrl($scope, Socket) { Socket.on('content:changed', function(data) { $scope.data = data; }); $scope.submitContent = function() { socket.emit('content:changed', $scope.data); }; }
Podría obtener realmente alta tecnología y crear una implementación de websocket que sincronice un modelo angular con el servidor. Cuando el cliente cambia algo, ese cambio se envía automáticamente al servidor. O si el servidor cambia, se envía al cliente.
Aquí hay un ejemplo de eso en una versión anterior de Angular, nuevamente usando socket.io: https://github.com/mhevery/angular-node-socketio
EDITAR : Para el n. ° 3, he estado usando Firebase para hacer esto.
fuente
Aquí hay una implementación que usa jetty en lugar de node. La parte angularjs se basa en la aplicación angular-seed. No estoy seguro de si el código angular es idiomático ... pero he probado que funciona. HTH -Todd.
TimerWebSocketServlet ver
https://gist.github.com/3047812
controllers.js
// ------------------------------------------------------------- // TimerCtrl // ------------------------------------------------------------- function TimerCtrl($scope, CurrentTime) { $scope.CurrentTime = CurrentTime; $scope.CurrentTime.setOnMessageCB( function (m) { console.log("message invoked in CurrentTimeCB: " + m); console.log(m); $scope.$apply(function(){ $scope.currentTime = m.data; }) }); } TimerCtrl.$inject = ['$scope', 'CurrentTime'];
services.js
angular.module('TimerService', [], function ($provide) { $provide.factory('CurrentTime', function () { var onOpenCB, onCloseCB, onMessageCB; var location = "ws://localhost:8888/api/timer" var ws = new WebSocket(location); ws.onopen = function () { if(onOpenCB !== undefined) { onOpenCB(); } }; ws.onclose = function () { if(onCloseCB !== undefined) { onCloseCB(); } }; ws.onmessage = function (m) { console.log(m); onMessageCB(m); }; return{ setOnOpenCB: function(cb){ onOpenCB = cb; }, setOnCloseCB: function(cb){ onCloseCB = cb; }, setOnMessageCB: function(cb){ onMessageCB = cb; } }; })});
web.xml
<servlet> <servlet-name>TimerServlet</servlet-name> <servlet-class>TimerWebSocketServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>TimerServlet</servlet-name> <url-pattern>/api/timer/*</url-pattern> </servlet-mapping>
fuente
Lo que busca es Firebase y Deployd . Firebase también viene con un adaptador que facilita su uso: http://angularfire.com/
fuente
Según el libro "Discover Meteor", los relojes / alcances de Angular son similares a los cálculos de Meteor con respecto a la reactividad ... pero Angular es solo para el cliente y brinda un control menos granular que Meteor.
Mi impresión es que usar Angular podría ser una mejor opción para agregar reactividad a una aplicación existente, mientras que Meteor se dispara cuando lo usa para todo. Pero todavía no tengo experiencia real con Angular (aunque he creado algunas aplicaciones pequeñas de Meteor).
fuente
Entonces, Andy Joslin ha mencionado la mejor solución en mi opinión en su respuesta, la tercera opción, que es mantener el estado bidireccionalmente a través de websockets o cualquier otra biblioteca asíncrona con la que esté tratando (esta sería la API de mensajes de Chrome para extensiones de Chrome y Apps, por ejemplo), y toddg ha dado un ejemplo de cómo se lograría. Sin embargo, en su ejemplo está implementando un anti-patrón en AngularJS: el servicio está llamando al controlador. En cambio, el modelo debe colocarse dentro del servicio y luego referenciarse desde el controlador.
Las devoluciones de llamada de socket de servicio modificarán el modelo de servicio y, como se hace referencia a él desde el controlador, actualizará la vista. Sin embargo, tenga cuidado si está tratando con tipos de datos primitivos o variables que se pueden reasignar, ya que necesitarán un control en el controlador para que esto funcione.
fuente