簡體   English   中英

AngularJS websockets太快

[英]AngularJS websockets too fast

我正在使用AngularJS為我的Web應用程序供電。 最近,我決定與RabbitMQ一起在Websockets上引入Stomp。 我一直遇到的一個問題是,有時后端發送的消息的頻率很高,以至於Angular無法觸發某些事件,從而導致進程丟失數據。

該應用程序相當復雜,因此有時一條消息可能會通過以下鏈

  1. StompJS Angular服務包裝器。 使用$ rootScope。$ broadcast在新消息到達時通知組件
  2. 注冊到$ rootScope上正在廣播的消息的控制器。 然后,控制器更新綁定或將另一個事件發送到組件以執行一些數據更新。

正如我提到的那樣,即使發送事件和填充值, 有時也無法正確更新范圍,但視圖仍未顯示更新后的值。 我用過$ 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
            };
        }
    ]);
  1. 您可能沒有在Angular摘要周期內觸發更新,這可以解釋為什么只得到一些更新。 嘗試使用摘要循環進行更新(將功能放入$ timeout塊中,這是在$ scope上的推薦方式。

    $ timeout(function(){doUpdate(dataFromMessageBus);});

  2. 如果收到大量消息,則應使用反跳功能,請參閱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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM