Javascript 如果外部应用程序更改了持久模型(服务器数据库),AngularJS 是否可以自动更新视图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11276520/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can AngularJS auto-update a view if a persistent model (server database) is changed by an external app?
提问by jpeskin
I'm just starting to familiarize with AngularJS, but I would like to build a web app that has a view that gets auto-upated in real-time (no refresh) for the user when something changes in the server-side database.
我刚刚开始熟悉 AngularJS,但我想构建一个 Web 应用程序,该应用程序具有一个视图,当服务器端数据库中的某些内容发生变化时,该视图会为用户实时自动更新(无刷新)。
Can AngularJS handle this (mostly) automatically for me? And if so, what is the basic mechanism at work?
AngularJS 可以为我自动处理这个(大部分)吗?如果是这样,工作的基本机制是什么?
For example, do you somehow setup AngularJS to poll the DB regularly for "model" changes? Or use some sort of Comet-like mechanism to notify AngularJS client-side code that the model has changed?
例如,您是否以某种方式设置 AngularJS 定期轮询数据库以获取“模型”更改?或者使用某种类似 Comet 的机制来通知 AngularJS 客户端代码模型已更改?
In my application, the challenge is that other (non-web) server-side software will be updating the database at times. But this question applies equally to pure web-apps where you might have multiple clients changing the database through AngularJS web clients, and they each need to be updated when one of them makes a change to the DB (model).
在我的应用程序中,挑战在于其他(非 Web)服务器端软件有时会更新数据库。但是这个问题同样适用于纯 Web 应用程序,其中您可能有多个客户端通过 AngularJS Web 客户端更改数据库,并且当其中一个对数据库(模型)进行更改时,每个客户端都需要更新。
回答by Andrew Joslin
You have a few choices...
你有几个选择...
You could do polling every X milliseconds using
$timeout
and$http
, or if the data you're using is hooked up to a REST service, you could use$resource
instead of$http
.You could create a service that uses some Websocket implementation and uses
scope.$apply
to handle changes that are pushed by the socket. Here's an example using socket.io, a 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); }; }
You could get really high tech and create a websocket implementation which syncs an Angular model with the server. When the client changes something, that change gets automatically sent to the server. Or if the server changes, it gets sent to the client.
Here's an example of that in an old version of Angular, again using socket.io: https://github.com/mhevery/angular-node-socketio
您可以使用
$timeout
and每 X 毫秒轮询一次$http
,或者如果您使用的数据连接到 REST 服务,您可以使用$resource
代替$http
.您可以创建一个使用某些 Websocket 实现并用于
scope.$apply
处理由套接字推送的更改的服务。下面是一个使用 socket.io 的例子,一个 node.js websocket 库: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 模型与服务器同步。当客户端更改某些内容时,该更改会自动发送到服务器。或者如果服务器发生变化,它会被发送到客户端。
这里,再次使用socket.io在老版本的角度的一个例子:https://github.com/mhevery/angular-node-socketio
EDIT: For #3, I've been using Firebaseto do this.
编辑:对于#3,我一直在使用Firebase来做到这一点。
回答by toddg
Here's an implementation that uses jetty instead node. The angularjs part is based on the angular-seed app. I'm not sure if the angular code is idiomatic...but I've tested that this works. HTH -Todd.
这是一个使用码头代替节点的实现。angularjs 部分基于 angular-seed 应用程序。我不确定角度代码是否是惯用的......但我已经测试过它是否有效。HTH-托德。
TimerWebSocketServlet see
TimerWebSocketServlet 见
https://gist.github.com/3047812
https://gist.github.com/3047812
controllers.js
控制器.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
服务.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
网页.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>
回答by Kenneth Lynne
What you are looking for is Firebaseand Deployd. Firebase comes with an adapter too that makes using it a breeze: http://angularfire.com/
您正在寻找的是Firebase和Deployd。Firebase 也带有一个适配器,使用起来变得轻而易举:http: //angularfire.com/
回答by cweekly
According to the "Discover Meteor" book, Angular watches/scopes are similar to Meteor's computations regarding reactivity... but Angular is client-only and gives less-granular control than Meteor.
根据“Discover Meteor”一书,Angular 手表/范围类似于 Meteor 的关于反应性的计算……但 Angular 仅适用于客户端,并且提供的控制粒度不如 Meteor。
My impression is that using Angular might be a better fit for adding reactivity to an existing app, whereas Meteor soars when you use it for the whole thing. But I have no real experience with Angular yet (though I have built some small Meteor apps).
我的印象是,使用 Angular 可能更适合为现有应用程序添加反应性,而当您将 Meteor 用于整个应用程序时,它会飙升。但是我对 Angular 还没有真正的经验(尽管我已经构建了一些小型 Meteor 应用程序)。
回答by bluehallu
So, Andy Joslin has mentioned the best solution in my opnion in his answer, the 3rd option, which is to maintain state bidirectionally via websockets or whatever other async library you're dealing with (this would be the Chrome message API for Chrome Extensions and Apps for instance), and toddg has given an example of how that would be achieved. However, in his example he is implementing an anti-pattern in AngularJS: the service is calling the controller. Instead, the model should be placed inside the service, and then referenced from the controller.
因此,Andy Joslin 在他的回答中提到了我的选项中的最佳解决方案,即第三个选项,即通过 websockets 或您正在处理的任何其他异步库双向维护状态(这将是 Chrome 扩展程序的 Chrome 消息 API 和例如应用程序),toddg 给出了一个如何实现的例子。然而,在他的例子中,他在 AngularJS 中实现了一个反模式:服务正在调用控制器。相反,模型应该放在服务中,然后从控制器中引用。
The service socket callbacks will modify the service model, and because it is referenced from the controller, it will update the view. Careful if you're dealing with primitive data types or variables that can be reassigned though, those will need a watch on the controller to make this work.
服务套接字回调将修改服务模型,并且因为它是从控制器引用的,它将更新视图。如果您正在处理可以重新分配的原始数据类型或变量,请小心,这些将需要在控制器上进行监视才能使其工作。