Может ли 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: служба вызывает контроллер. Вместо этого модель должна быть помещена внутри службы, а затем ссылаться на контроллер.
Обратные вызовы сокета службы изменят модель обслуживания, и поскольку на нее ссылаются контроллеры, она обновит представление. Будьте осторожны, если вы имеете дело с примитивными типами данных или переменными, которые могут быть переназначены, тем не менее, для выполнения этой работы вам понадобятся часы на контроллере.