web-dev-qa-db-fra.com

AngularJS peut-il mettre à jour automatiquement une vue si un modèle persistant (base de données du serveur) est modifié par une application externe?

Je commence tout juste à me familiariser avec AngularJS, mais j'aimerais construire une application Web dotée d'une vue qui s'auto-actualise en temps réel (aucune actualisation) pour l'utilisateur lorsque quelque chose change dans la base de données côté serveur.

AngularJS peut-il gérer cela (principalement) automatiquement pour moi? Et si oui, quel est le mécanisme de base à l'œuvre?

Par exemple, configurez-vous d’une manière ou d’une autre AngularJS pour qu’il interroge régulièrement la base de données afin de connaître les modifications apportées au modèle? Ou utilisez une sorte de mécanisme ressemblant à Comet pour informer le code côté client d’AngularJS que le modèle a été modifié?

Dans mon application, le défi est que d'autres logiciels (non Web) côté serveur mettront à jour la base de données à l'occasion. Mais cette question s’applique également aux applications Web pures où plusieurs clients peuvent modifier la base de données via des clients Web AngularJS et doivent être mis à jour chaque fois que l’un d’eux modifie la base de données (modèle).

82
jpeskin

Vous avez quelques choix...

  1. Vous pouvez interroger toutes les X millisecondes avec $timeout et $http, ou si les données que vous utilisez sont connectées à un service REST, vous pouvez utiliser $resource au lieu de $http.

  2. Vous pouvez créer un service qui utilise une implémentation de Websocket et utilise scope.$apply pour gérer les modifications poussées par le socket. Voici un exemple utilisant socket.io, une bibliothèque websocket 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);
        };
    }
    
  3. Vous pouvez obtenir une technologie de pointe et créer une implémentation Websocket qui synchronise un modèle Angular avec le serveur. Lorsque le client change quelque chose, ce changement est automatiquement envoyé au serveur. Si le serveur change, il est envoyé au client.
    Voici un exemple de cela dans une ancienne version de Angular, utilisant à nouveau socket.io: https://github.com/mhevery/angular-node-socketio

[~ # ~] éditer [~ # ~] : Pour # 3, j'ai utilisé Firebase pour le faire .

96
Andrew Joslin

Voici une implémentation qui utilise jetty à la place du noeud. La partie angularjs est basée sur l'application angular-seed. Je ne suis pas sûr si le code angular est idiomatique ... mais j'ai testé le fonctionnement de ce logiciel. HTH -Todd.

TimerWebSocketServlet voir

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>
15
toddg

Ce que vous recherchez, c'est Firebase et Deployd . Firebase est livré avec un adaptateur qui facilite son utilisation: http://angularfire.com/

3
Kenneth Lynne

Ainsi, Andy Joslin a mentionné la meilleure solution de mon côté dans sa réponse, la troisième option, qui consiste à maintenir l’état de manière bidirectionnelle via des websockets ou toute autre bibliothèque async à laquelle vous avez affaire (ce serait le Chrome API de message pour Chrome Extensions and Apps par exemple), et toddg a donné un exemple de la manière dont cela serait réalisé. Cependant, dans son exemple, il implémente un anti-motif dans AngularJS : le service appelle le contrôleur, mais le modèle doit être placé dans le service, puis référencé à partir du contrôleur.

Les rappels de socket de service modifieront le modèle de service et, comme il est référencé à partir du contrôleur, la vue sera mise à jour. Attention, si vous avez affaire à des types de données primitifs ou à des variables pouvant être réaffectées, il faudra une surveillance sur le contrôleur pour que cela fonctionne.

0
bluehallu

Selon le livre "Discover Meteor", Angular les montres/oscilloscopes sont similaires aux calculs de Meteor concernant la réactivité ... mais Angular ne concerne que le client et offre un contrôle moins granulaire que Meteor.

Mon impression est que l'utilisation de Angular pourrait être un meilleur moyen d'ajouter de la réactivité à une application existante, alors que Meteor monte en flèche lorsque vous l'utilisez pour la totalité. Mais je n'ai pas encore de réelle expérience avec Angular (même si j'ai construit quelques petites applications Meteor).

0
cweekly