Чи може AngularJS автоматично оновити подання, якщо стійку модель (базу даних сервера) змінив зовнішній додаток?


81

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

Чи може AngularJS обробляти це (здебільшого) автоматично для мене? І якщо так, то який основний механізм у роботі?

Наприклад, ви якось налаштовуєте AngularJS для регулярного опитування БД щодо змін "моделі"? Або скористатися якимсь кометоподібним механізмом, щоб повідомити код клієнта AngularJS про те, що модель змінилася?

У моїй програмі проблема полягає в тому, що інше (не в Інтернеті) серверне програмне забезпечення час від часу оновлюватиме базу даних. Але це питання однаково стосується і чистих веб-програм, де у вас може бути кілька клієнтів, які змінюють базу даних через веб-клієнти AngularJS, і кожного з них потрібно оновити, коли один із них вносить зміни в БД (модель).


Я хотів би додати, що з тих пір я виявив, що Meteor робить все це для вас у фреймворці, тому зараз це моє найкраще рішення. У майбутньому може знову перевірити Angular.
jpeskin

Метеор може бути ще надто "свіжим" - добре розігратися, але не зарекомендував себе у великому виробництві (безпечно / масштабованість / продуктивність / тощо). Автентифікація була додана трохи більше місяця тому. Виглядає добре, але зачекає.
Олексій Окрушко

@jpeskin Привіт. Я приблизно про те, де ви були, коли ви задавали це запитання. Що ти врешті зробив? (Я хотів би використовувати Angular). З повагою
mark1234

Відповіді:


97

У вас є кілька варіантів ...

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

  2. Ви можете створити службу, яка використовує певну реалізацію Websocket і використовує scope.$applyдля обробки змін, які виштовхуються сокетом. Ось приклад використання socket.io, веб-бібліотеки 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. Ви можете отримати справді високі технології та створити реалізацію websocket, яка синхронізує модель Angular із сервером. Коли клієнт щось змінює, ця зміна автоматично надсилається на сервер. Або якщо сервер змінюється, він надсилається клієнту.
    Ось приклад цього у старій версії Angular, знову використовуючи socket.io: https://github.com/mhevery/angular-node-socketio

EDIT : Для №3 для цього я використовую Firebase .


Дякую за таку ретельну відповідь із кількома варіантами! З нетерпінням чекаю осмислення цього, коли я дізнаюся більше про Angular :)
jpeskin

4
github.com/mhevery/angular-node-socketio - мала орфографічну помилку. виправлено
Ендрю Джослін

Дякуємо за просту для розуміння відповідь, дуже корисну.
mystrdat

Як би ви продовжували розв’язувати обробники подій, якщо контролер потрібно знищити?
RushPL

Брайан Форд має чудовий підхід, який дозволяє вам переглядати систему і очищення подій $ scope. І робить це справді чистим загалом. github.com/btford/angular-socket-io . Подивіться на socket.forward ()
Ендрю Джослін

15

Ось реалізація, яка використовує jetty замість node. Частина angularjs базується на додатку angular-seed. Я не впевнений, що кутовий код ідіоматичний ... але я перевірив, що це працює. HTH -Тодд.

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>

Це яскравий приклад. Я тільки вивчаю Angular.js, і мені було цікаво, чи є у вас повний додаток із шаблонами тощо, для навчання?
mac


0

Згідно з книгою "Відкрийте Метеор", годинникові прилади / сфери дії схожі на обчислення Метеора щодо реакційної здатності ... але Angular призначений лише для клієнтів і забезпечує менш детальний контроль, ніж Метеор.

У мене таке враження, що використання Angular може бути кращим варіантом для додавання реактивності до існуючого додатка, тоді як Meteor злітає, коли ви використовуєте його для всього. Але я ще не маю реального досвіду роботи з Angular (хоча я створив кілька невеликих додатків Meteor).


0

Отже, Енді Джослін у своїй відповіді згадав найкраще рішення в моєму висновку, третій варіант, який полягає у підтримці стану у двонаправленому вигляді через веб-сокети або будь-яку іншу асинхронну бібліотеку, з якою ви маєте справу (це буде API повідомлень Chrome для розширень Chrome і Наприклад, програми), а toddg наводить приклад того, як цього можна досягти. Однак у своєму прикладі він реалізує анти-шаблон у AngularJS: служба викликає контролер. Натомість модель слід розмістити всередині служби, а потім посилатися на неї з контролера.

Зворотні виклики сервісного сокета змінять модель служби, а оскільки на неї посилаються з контролера, оновлення подання. Обережно, якщо ви маєте справу з примітивними типами даних або змінними, які можуть бути перепризначені, тим самим для цього потрібен годинник на контролері.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.