Может ли AngularJS автоматически обновлять представление, если внешняя программа изменяет постоянную модель (серверную базу данных)?

Я только начинаю знакомство с AngularJS, но я хотел бы создать веб-приложение, которое имеет представление, которое автоматически обновляется в режиме реального времени (без обновления) для пользователя, когда что-то меняется на стороне сервера базы данных.

Может ли AngularJS обрабатывать это (главным образом) автоматически для меня? И если да, то каков основной механизм на работе?

Например, вы как-то настраиваете AngularJS для регулярного опроса базы данных для "модельных" изменений? Или используйте какой-то комет-подобный механизм, чтобы уведомить клиентский код AngularJS о том, что модель изменилась?

В моем приложении проблема заключается в том, что другое (не веб-сервер) программное обеспечение на стороне будет периодически обновлять базу данных. Но этот вопрос в равной степени относится и к чистым веб-приложениям, где у вас может быть несколько клиентов, изменяющих базу данных через веб-клиенты AngularJS, и каждый из них нуждается в обновлении, когда один из них вносит изменения в БД (модель).

Ответ 1

У вас есть несколько вариантов...

  • Вы можете делать опрос каждые X миллисекунд, используя $timeout и $http, или если данные, которые вы используете, подключены к службе REST, вы можете использовать $resource вместо $http.

  • Вы можете создать службу, которая использует некоторую реализацию Websocket, и использует scope.$apply для обработки изменений, которые нажимают на сокет. Вот пример использования socket.io, node.js websocket library:

    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);
        };
    }
    
  • Вы можете получить действительно высокие технологии и создать реализацию websocket, которая синхронизирует модель Angular с сервером. Когда клиент что-то меняет, это изменение автоматически отправляется на сервер. Или, если сервер изменится, он будет отправлен клиенту.
    Вот пример этого в старой версии Angular, снова используя socket.io: https://github.com/mhevery/angular-node-socketio

EDIT. Для # 3 я использовал Firebase для этого.

Ответ 2

Здесь реализована реализация, использующая причал node. Часть угловой части основана на приложении angular -seed. Я не уверен, что код angular является идиоматическим... но я тестировал, что это работает. HTH -Todd.

TimerWebSocketServlet см.

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>

Ответ 3

То, что вы ищете, Firebase и Deployd. Firebase поставляется с адаптером, который делает его легким: http://angularfire.com/

Ответ 4

В соответствии с книгой "Discover Meteor" часы Angular часы/области сходны с расчетами Метеор относительно реактивности... но Angular является клиентом и обеспечивает менее гранулированный контроль, чем Meteor.

Мое впечатление, что использование Angular может быть лучше подходит для добавления реактивности к существующему приложению, тогда как Meteor парит, когда вы используете его для всего. Но у меня нет реального опыта работы с Angular (хотя я создал небольшие приложения Meteor).

Ответ 5

Итак, Энди Хослин упомянул о лучшем решении в моем вопросе в его ответе, третьем варианте, который заключается в том, чтобы поддерживать состояние в двунаправленном режиме через веб-сайты или любую другую асинхронную библиотеку, с которой вы имеете дело (это будет API сообщений Chrome для Например, расширения Chrome и приложения), а toddg привел пример того, как это будет достигнуто. Однако в своем примере он реализует анти-шаблон в AngularJS: служба вызывает контроллер. Вместо этого модель должна быть помещена внутри службы, а затем ссылаться на контроллер.

Обратные вызовы сокета службы изменят модель обслуживания, и поскольку на нее ссылаются контроллеры, она обновит представление. Будьте осторожны, если вы имеете дело с примитивными типами данных или переменными, которые могут быть переназначены, тем не менее, для выполнения этой работы вам понадобятся часы на контроллере.