我对Angular和JS都比较陌生,但请耐心等待。我见过很多类似的问题,但这些问题似乎都没有回答我的问题。
我有以下服务,订阅包含Twitter消息的消息流
angular.module('twitterstream.services', [])
.factory('tweetService', function() {
var tweets = [];
var tweetFeed = new EventSource("/feed");
tweetFeed.addEventListener("message", feedCallback, false);
return {
getTweets: getTweets
};
function getTweets() {
return tweets;
}
function feedCallback(message) {
var tweet = JSON.parse(message.data);
tweets.push(tweet);
}
})
在我的控制器中,我正在观看服务的tweets
属性:
angular.module('twitterstream.controllers', ['twitterstream.services'])
.controller('tweetController', ['$scope', 'tweetService', function($scope, tweetService) {
$scope.tweets = [];
$scope.$watch(
function() {
return tweetService.getTweets();
},
function(newVal, oldVal) {
$scope.tweets = newVal;
}
);
}]);
这是我的index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="bower_components/angular/angular.js"></script>
<script src="scripts/app.js"></script>
<script src="scripts/controllers/controllers.js"></script>
<script src="scripts/services/services.js"></script>
</head>
<body data-ng-app="twitterstream">
Hello jerks
<br>
<div data-ng-controller="tweetController">
<ul>
<li data-ng-repeat="tweet in tweets">
{{tweet.text}}
</li>
</ul>
</div>
</body>
</html>
现在,问题在于:<ul>
未获得更新。
要明确:
tweets
正在更新tweets
也会更新但是UI没有得到更新。但是,如果我打电话
angular.element($("div")).inheritedData().$scope.$apply();
从开发人员控制台,整个DOM按预期很好地刷新。
这促使我在控制器中手动插入$ apply调用:
$scope.$watch(
function() {
return tweetService.getTweets();
},
function(newVal, oldVal) {
$scope.tweets = newVal;
$scope.$apply(); // <---- Right over here
}
);
但是,只要应用程序启动,就会产生以下错误:
[$rootScope:inprog] $digest already in progress
我在SO上找到的大多数示例都没有将对EventSource的订阅分成服务,只是将所有内容都保存在一个控制器中。当然,我的服务中没有$ scope对象,所以我不能在EventSource回调中调用$ apply。
最优雅的解决方案是什么?
答案 0 :(得分:2)
我会轻易做到:
angular.module('twitterstream', []);
angular.module('twitterstream.services', [])
.factory('tweetService', function() {
var tweets = [];
var tweetFeed = new EventSource("/feed");
// the factory returns a function waiting for a callback that will handle the controller
return {
getTweets: function(callback) {
tweetFeed.addEventListener("message", callback, false);
}
};
});
angular.module('twitterstream.controllers', ['twitterstream.services'])
.controller('tweetController', ['$scope', 'tweetService', function($scope, tweetService) {
// the controller will assign the value when 'message' event is ready
$scope.tweets = tweetService.getTweets(function(response) {
var tweets = JSON.parse(response.data);
$scope.tweets = tweets;
});
}]);
我希望这可以帮助你:)