I am fetching data from websocket in a factory. Every time a message arrives I update it.
In my controller I have bound the same inside the $scope. However when the websocket message comes, UI doesn't get updated.
After doing a lot of search I figured out that I need to call $scope.$apply if I need to update the UI (if changes are not saved by using any angular method).
I set up a timer using setInterval to call $scope.$apply every second. But it is a hack. I would like to remove this. Is there a way to tell angular to refresh from inside the factory, without using this hack?
Factory:
app.factory('StocksFactory', function() {
...
factory.stocksCurrentPrices = {};
// Subscribe to the websocket for stock prices
const stocksSocket = new WebSocket('ws://...');
stocksSocket.onmessage = function(event) {
// Adding to current prices
factory.stocksCurrentPrices[..] = ...;
};
return factory;
});
Controller:
app.controller('StocksController', function($scope, StocksFactory) {
$scope.stocks = StocksFactory.stocksCurrentPrices;
// HACK This is used to force the digest every second as the changes in $scope.stocks
// was not reflected in the UI
setInterval(function() {
$scope.$apply();
}, 1000);
});
You can not use $scope
in an AngularJS service, since services do not belong to any scope, but they are singlenton through the application.
But you CAN inject the $rootScope
into the service and notify through the entire application, like this:
app.factory('StocksFactory', function($rootScope, $timeout) {
...
factory.stocksCurrentPrices = {};
// Subscribe to the websocket for stock prices
const stocksSocket = new WebSocket('ws://...');
stocksSocket.onmessage = function(event) {
// Adding to current prices
factory.stocksCurrentPrices[..] = ...;
// notify of changes
$timeout(function() {
$rootScope.$apply();
})
};
return factory;
});
Notice that:
$rootScope.$apply();
inside a $timeout
in order to Prevent error $digest already in progress $rootScope.$broadcast
您可以在工厂中注入$rootScope
并在其中使用$broacast
来发出已更改的内容。
Add $rootScope
in your factory and broadcast a message when the stockmarket has change.
app.factory('StocksFactory', ['$rootScope', function($rootScope) {
var factory = {}
factory.stocksCurrentPrices = {};
const stocksSocket = new WebSocket('ws://...');
stocksSocket.onmessage = function(event) {
factory.stocksCurrentPrices[..] = ...;
$rootScope.$broadcast('stocks-just-change')
};
return factory;
}])
Then in your controller just listen for that broadcast message and update your $scope.stocks
app.controller('StocksController', function($scope, StocksFactory) {
$scope.stocks = StocksFactory.stocksCurrentPrices;
$scope.$on('stocks-just-change', function(){
$scope.stocks = StocksFactory.stocksCurrentPrices;
//$scope.$apply() //use this if you'll receive updates very very fast
}
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.