[英]AngularJS websockets too fast
我正在使用AngularJS为我的Web应用程序供电。 最近,我决定与RabbitMQ一起在Websockets上引入Stomp。 我一直遇到的一个问题是,有时后端发送的消息的频率很高,以至于Angular无法触发某些事件,从而导致进程丢失数据。
该应用程序相当复杂,因此有时一条消息可能会通过以下链
正如我提到的那样,即使发送事件和填充值, 有时也无法正确更新范围,但视图仍未显示更新后的值。 我用过$ scope。$ apply,$ timeout,$ scope。$ digest似乎没有任何工作...例如,如果我有2个数据包一个接一个地出现,并且套接字之间几乎没有延迟,或者没有延迟,但是如果有相同的一段代码,则功能正常。 如何克服呢?
为了进一步举例说明用户提出的一些问题:
我将以最简单的示例为例:我从后端运行的工作获取进度报告。 基本上,它告诉我在Cassandra数据库中已经写了多少行。 因此,我收到诸如{写信:8000,总数:4000000}之类的通知。 随着工作人员在数据库中的写入,“写”正在增加,并且由于有多个工作人员,有时这些通知会很快推送。 我编写了一个自定义的网格组件,用于侦听grid:updateCell之类的事件(这使我可以使用进度报告来更新单元格)。 每当套接字上有数据包时,我都会广播该事件($ scope。$ broadcast,因为网格是控制器页面的子级)。 我注意到,虽然捕获了事件,但并非所有来自套接字的更新都反映在UI中,并且成功更新数据模型也触发了Grid事件,但不是UI
在我看来,您可能在这里发生了一些事情。
1)使用$ scope。$ broadcast缩小范围,如果您有很多嵌套的范围,可能会很沉重。 我更喜欢将事件侦听器附加到$ rootScope并使用$ emit,它只广播到当前作用域,并且速度更快。 我为此提供以下服务
/**
* @ngdoc service
* @name someModule.eventbus
* @requires $rootScope
*
* @description
* Provides a eventing mechanism when a user cna broadcast and subscribe to application wide events.
*/
angular.module('someModule').factory('eventbus', [
'$rootScope',
function ($rootScope) {
/**
* @ngdoc function
* @name subscribe
* @methodOf someModule.eventbus
*
* @description
* Subscribes a callback to the given application wide event
*
* @param {String} eventName The name of the event to subscribe to.
* @param {Function} callback A callback which is fire when the event is raised.
* @return {Function} A function tht can be called to unsubscrive to the event.
*/
var subscribe = function (eventName, callback) {
return $rootScope.$on(eventName, callback);
},
/**
* @ngdoc function
* @name broadcast
* @methodOf someModule.eventbus
*
* @description
* Broadcasts the given event and data.
*
* @param {String} eventName The name of the event to broadcast.
* @param {object} data A data object that will be passed along with the event.
*/
broadcast = function (eventName, data) {
$rootScope.$emit(eventName, data);
};
return {
subscribe: subscribe,
broadcast: broadcast
};
}
]);
您可能没有在Angular摘要周期内触发更新,这可以解释为什么只得到一些更新。 尝试使用摘要循环进行更新(将功能放入$ timeout块中,这是在$ scope上的推荐方式。
$ timeout(function(){doUpdate(dataFromMessageBus);});
如果收到大量消息,则应使用反跳功能,请参阅lodash-debouce 。 一个人只能真正处理大约200毫秒的块,因此通常每200毫秒进行更新将是某人可以接受的最多。我个人大约每秒进行一次处理,例如交易应用程序等。
(使用lodash-反跳)
function (messageBus) {
var debounceFn = _.debounce(function () {
$timeout(function() {
doUpdate(data);
});
}, 1000);
// just assuming here about your socket / message bus stuff
messageBus.onMessageRecieved(function () {
//Call debounce function which will only actually call the inner func every 1000ms
debounceFn();
});
}
我之前遇到过同样的问题,我可以通过包装websocket传入消息处理程序来解决此问题,该处理程序将在下面更新我的Angular Grid:
$scope.$apply(function () {
//your code to update the Angular UI
});
例:
/**
* @ngdoc function
* @description
* On Connect. Callback to subscribe to specific socket destination.
*/
function _subscribeBcQueue(){
var uuid = SessionService.getUuid();
var userBcQueue = CONFIG.SOCKET.bcQueue+'/'+uuid
var subscription = $stomp.subscribe(userBcQueue, function (payload, headers, message) {
_onBcMessageHandler(message)
}, {})
}
/**
* @ngdoc function
* @description
* OnBcMessageHandler. Callback function to handle the incoming direct message.
*/
function _onBcMessageHandler(message){
//TODO Process the broadcasting status message
var bcMsg = JSON.parse(message.body);
console.log("Broadcasting status message:" + bcMsg);
_updateBcJobGridRow(bcMsg)
}
function _updateBcJobGridRow(job) {
$scope.$apply(function () {
//Get the old JobGridRow
console.log("jobId: " + JSON.stringify(job.id));
var oldJobGridRow = $filter('filter')(vm.gridOptions.data, {id: job.id})[0];
console.log("oldJobGridRow: " + JSON.stringify(oldJobGridRow));
if (oldJobGridRow) {
var newJobGridRow = _getBcJobGridRow(job);
console.log("newJobGridRow: " + JSON.stringify(newJobGridRow));
oldJobGridRow.progress = newJobGridRow.progress;
oldJobGridRow.percentage = newJobGridRow.percentage;
oldJobGridRow.status = newJobGridRow.status;
oldJobGridRow.total = newJobGridRow.total;
oldJobGridRow.sent = newJobGridRow.sent;
oldJobGridRow.recipients = newJobGridRow.recipients;
}
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.