如何减少AngularJS 1.3中的观察者 - 性能问题

时间:2017-11-27 13:48:16

标签: angularjs performance data-binding angularjs-scope angularjs-watch

仓库正在使用的内部Web软件。它包含一个订单表,其中包含需要扫描并准备交付的物品。

它有3个排序选项,12个主要和次要过滤器。该表由ng-repeat创建,并且有很多范围变量的引用。

它包含一个主要数组,里面有大约2000个对象,并且还有一些对象助手 - 有些很小,有些很大。

主阵列需要每分钟刷新一次以刷新表格,因为有几个人同时使用它。

数组示例:

[0:{Barcode:"1234", Description:"Hisense 50 Inch  Quad Core UHD 4K Smart Led TV", Docbal: 0, Docdate:"17/10/2017", Docnum:111111, FastOrder:0, GrpCode:111, NotInStock:true, Notes:"Hello", OnHand:0, OpenQty:1, OrderNumber:1736604, PartOfNotInStock:true, Total:2123, cntOrdersToDemand:6, commited:true, isMultiple:false, multipleChecked:true, relevantStock:0, scanned:0, shelf:null}]

每次扫描都会执行一系列事件,这些事件在客户端对象中包含大量数据搜索和更新。

几乎所有的函数和变量都在范围内,并被ng-click等调用和使用。

一开始没有性能问题,因为阵列非常小,但现在它变大了,我看到程序中有多达60,000个观察者(!)。

是否有可能通过一些更改来维持当前结构?

表tr创建:

<tr ng-repeat="docs in itemsData | filter: searchText | filter: filterTable(currentFilter) : true | orderBy: orderType" ng-class="{'notinstock':docs.NotInStock,'text-center': true, 'marked': docs.OpenQty==docs.scanned}" ng-show="( (multipleDocs==docs.isMultiple) || (multipleDocs=='all') ) && ((docs.Docbal>0)!=noDebt) && ((docs.PartOfNotInStock>0)!=notInStock) && ((docs.FastOrder==0) != fastOrder)" docnum="{{docs.Docnum}}" orderNumber="{{docs.OrderNumber}}" barcode="{{docs.Barcode}}">
                <td>
                  <div class="copyDiv" ng-show="(!docs.FastOrder)">
                    <i ng-click="searchItems(docs.Docnum, 'doc')"  title="לחיצה לחיפוש / חזרה מחיפוש" ng-class="{'fa fa-search-minus': searchOnDoc==true, 'fa fa-search-plus':searchOnDoc==false}" class="searchIcon itemClick" aria-hidden="true"></i> 
                    <span title="לחיצה להעתקה" ng-click="clipboardCopyDoc('doc'+$index)" id="copyClickDoc{{'doc'+$index}}" class="clipboard itemClick" ngclipboard data-clipboard-text="{{docs.Docnum}}"> {{docs.Docnum}}</span>
                  </div>
                  <div class="docDate" ng-show="(!docs.FastOrder)">{{docs.Docdate}}</div>
                  <span ng-switch on="docs.shipping" ng-click="openInvoice(docs.Docnum)" title="{{ docs.FastOrder ? '' : 'לחיצה לצפייה בפרטי חשבונית' }}" ng-class="{'itemClick' : !docs.FastOrder}">

                    <span ng-switch-when="shipping" class="label label-by">Chita</span>
                    <span ng-switch-when="shipping_ev" class="label label-purplew">Buzzr</span>
                    <span ng-switch-when="pickup" class="label label-bw">איסוף</span>
                    <span ng-switch-when="boxit" class="label label-pinkw">Boxit</span>
                    <span ng-switch-when="postil" class="label label-rw">דואר</span>
                    <span ng-switch-default class="label label-brownw">לא צוין</span>

                  </span>
                  <span ng-show="docs.FastOrder" ng-click="cancelFastOrderSure(docs.OrderNumber)"  class="label label-danger itemClick cancelOrderBt" title="לחיצה לביטול ההזמנה המהירה"><i class="fa fa-fast-backward"></i> לחץ כדי להחזיר למכירות</span>
                </td>
                <td>
                  <div class="copyDiv">
                      <i ng-click="searchItems(docs.OrderNumber, 'doc')"  title="לחיצה לחיפוש / חזרה מחיפוש" ng-class="{'fa fa-search-minus': searchOnDoc==true, 'fa fa-search-plus':searchOnDoc==false}" class="searchIcon itemClick" aria-hidden="true"></i> 
                      <span title="לחיצה להעתקה" ng-click="clipboardCopyDoc('ord'+$index)" id="copyClickDoc{{'ord'+$index}}" class="clipboard itemClick" ngclipboard data-clipboard-text="{{docs.OrderNumber}}"> {{docs.OrderNumber}}</span>
                    </div>
                    <div class="docDate" ng-show="(docs.FastOrder)">{{docs.Docdate}}</div>
                      <span class="itemClick" ng-click="openOrder(docs.OrderNumber)" title="לחיצה לצפייה בפרטי ההזמנה">
                      <span ng-show="docs.FastOrder" class="label label-danger"><i class="fa fa-fast-backward"></i> הזמנה מהירה</span>
                      <span ng-show="!docs.FastOrder" class="label label-default">הזמנה רגילה</span>
                    </span>
                </td>
                <td>
                  <div class="copyDiv">
                    <i ng-click="searchItems(docs.Barcode, 'bar')"  title="לחיצה לחיפוש / חזרה מחיפוש" ng-class="{'fa fa-search-minus': searchOnBar ==true, 'fa fa-search-plus':searchOnBar ==false}" class="searchIcon itemClick" aria-hidden="true"></i> 
                    <span title="לחיצה להעתקה" ng-click="clipboardCopyBar($index)" id = "copyClickBar{{$index}}"class = "clipboard itemClick" ngclipboard data-clipboard-text="{{docs.Barcode}}"> {{docs.Barcode}}</span>
                  </div>
                </td>
                <td ng-bind-html="renderDoc(docs)"></td>
                <td class="itemClick" title="לחיצה להצגת סיריאלים זמינים" ng-click="peekAtSerials(docs.Barcode,docs.Docnum,docs.OrderNumber)">{{docs.scanned}}/{{docs.OpenQty}}</td>
                <td class="notes" ng-bind-html="renderHtml(docs.Notes)"></td>
                <td>{{docs.cntOrdersToDemand}}/{{docs.relevantStock}}</td> 
                <td>{{ getShelf(docs); }}</td>
                <td class="balance" ng-bind-html="renderHtml(getBal(docs.Docbal))"></td>
              </tr>

该程序还需要在平板电脑上运行,因此这种使用如此多的计算问题为客户带来负担的架构 - 使用如此多的内存和资源 - 让我想知道是否需要将应用程序更改为完全基于服务器端。

我已经尝试过只使用JavaScript创建表,然后编译它。它将观察者减少到1600,但它占用了大量的内存和CPU,每次刷新表时,程序都会卡住几秒钟。这也意味着每个过滤器都需要再次创建。有更好的方法吗?

我做了什么:

HTML:

<tbody id="tBody" compile="tr" ng-show="trNow"></tbody>
<tbody id="tBody" compile="tr2" ng-show="!trNow"></tbody>

编译指令:

myApp.directive('compile', ['$compile', function ($compile) {
    return function(scope, element, attrs) {
        scope.$watch(
            function(scope) {
                return scope.$eval(attrs.compile);
            },
            function(value) {
                element.html(value);
                $compile(element.contents())(scope);
            }
        );
    };
}]);

创建表的函数:

function makeTable(){
    makeTr(function(tr){
        switch($scope.trNow){
            case true: //tr
                    $scope.tr2 = tr;
                    $scope.trNow = false;
                    $scope.tr = "";
            break;
            case false: //tr2
                $scope.tr = tr;
                $scope.trNow = true;
                $scope.tr2 = "";
            break;
        }
    }
    );

}
async function makeTr(callBack){

var tr = "";

    for (var i=0; i<itemsDataView.length; i++){
        var titleText= itemsDataView[i].FastOrder ? '' : 'לחיצה לצפייה בפרטי חשבונית';
        var trClassNIS = itemsDataView[i].NotInStock ? 'notinstock' : '';
        var trClassMark = (itemsDataView[i].OpenQty == itemsDataView[i].scanned) ? 'marked' : '';
        var trClass = itemsDataView[i].NotInStock ? 'notinstock' : '';
        var trClass = itemsDataView[i].NotInStock ? 'notinstock' : '';
        var trClass = itemsDataView[i].NotInStock ? 'notinstock' : '';
        var showSearch = $scope.searchOnDoc==true ? 'fa fa-search-minus' : 'fa fa-search-plus';
        var showNoFast = !itemsDataView[i].FastOrder ? '<div class="copyDiv">'+
                        '<i ng-click="searchItems('+itemsDataView[i].Docnum+',\'doc\')" title="לחיצה לחיפוש / חזרה מחיפוש" class="'+showSearch+' searchIcon itemClick" aria-hidden="true"></i>'+
                        '<span title="לחיצה להעתקה" ng-click="clipboardCopyDoc(\'doc\'+'+i+')" id="copyClickDodoc'+i+'" class="clipboard itemClick" ngclipboard data-clipboard-text="'+ itemsDataView[i].Docnum+'"> '+itemsDataView[i].Docnum+'</span>'+
                        '</div><div class="docDate">'+itemsDataView[i].Docdate+'</div>' : '';
        var switchShippingClass = !itemsDataView[i].FastOrder ? 'itemClick' : '';       
        var switchShipping; 
        switch(itemsDataView[i].shipping){
            case "shipping":
                switchShipping = '<span class="label label-by">Chita</span>';
            break;
            case "shipping_ev":
                switchShipping = '<span class="label label-purplew">Buzzr</span>';
            break;
            case "pickup":
                switchShipping ='<span class="label label-bw">איסוף</span>';
            break;
            case "boxit":
                switchShipping ='<span class="label label-pinkw">Boxit</span>';
            break;
             case "postil":
                switchShipping ='<span class="label label-rw">דואר</span>';
            break;
            default:
                switchShipping ='<span class="label label-brownw">לא צוין</span>';
        }
         var fastOrderSpan = itemsDataView[i].FastOrder ? '<br><span ng-click="cancelFastOrderSure('+itemsDataView[i].OrderNumber+')"  class="label label-danger itemClick cancelOrderBt" title="לחיצה לביטול ההזמנה המהירה"><i class="fa fa-fast-backward"></i> לחץ לביטול הזמנה מהירה</span>' : "";  
         var fastOrderDiv = itemsDataView[i].FastOrder ? '<div class="docDate">'+itemsDataView[i].Docdate+'</div>' : ""; 
          var fastOrdeSpanYesNo = itemsDataView[i].FastOrder ? '<span class="label label-danger"><i class="fa fa-fast-backward"></i> הזמנה מהירה</span>' : '<span class="label label-default">הזמנה רגילה</span>'; 

        tr+='<tr class="'+trClassNIS +' text-center '+trClassMark+'" docnum="'+ itemsDataView[i].Docnum+'" orderNumber="'+ itemsDataView[i].OrderNumber+' "barcode="'+ itemsDataView[i].Barcode+'">'+
                '<td>'+showNoFast+
                  '<span ng-click="openInvoice('+itemsDataView[i].Docnum+')" title="'+ titleText +'" class="'+switchShippingClass+'">'+
                   switchShipping+
                  '</span>'+
                   fastOrderSpan+
                '</td>'+
                '<td>'+
                  '<div class="copyDiv">'+
                      '<i ng-click="searchItems('+itemsDataView[i].OrderNumber+', \'doc\')"  title="לחיצה לחיפוש / חזרה מחיפוש" class="'+showSearch+' searchIcon itemClick" aria-hidden="true"></i> '+
                      '<span title="לחיצה להעתקה" ng-click="clipboardCopyDoc(\'ord\'+'+i+')" id="copyClickDocord'+i+'" class="clipboard itemClick" ngclipboard data-clipboard-text="'+itemsDataView[i].OrderNumber+'"> '+itemsDataView[i].OrderNumber+'</span>'+
                    '</div>'+
                    fastOrderDiv+
                      '<span class="itemClick" ng-click="openOrder('+itemsDataView[i].OrderNumber+')" title="לחיצה לצפייה בפרטי ההזמנה">'+
                      fastOrdeSpanYesNo+
                    '</span>'+
                '</td>'+
                '<td>'+
                    '<div class="copyDiv">'+
                          '<i ng-click="searchItems('+itemsDataView[i].Barcode+', \'bar\')"  title="לחיצה לחיפוש / חזרה מחיפוש" class="'+showSearch+' searchIcon itemClick" aria-hidden="true"></i> '+
                          '<span title="לחיצה להעתקה" ng-click="clipboardCopyBar('+i+')" id = "copyClickBar{{'+i+'}}" class = "clipboard itemClick" ngclipboard data-clipboard-text="'+itemsDataView[i].Barcode+'"> '+itemsDataView[i].Barcode+'</span>'+
                    '</div>'+
                '</td>'+
                '<td>'+$scope.renderDoc(itemsDataView[i])+'</td>'+
                '<td class="itemClick" title="לחיצה להצגת סיריאלים זמינים" ng-click="peekAtSerials('+itemsDataView[i].Barcode+', '+itemsDataView[i].Docnum+','+itemsDataView[i].OrderNumber+')">'+itemsDataView[i].scanned+'/'+itemsDataView[i].OpenQty+'</td>'+
                '<td class="notes">'+$scope.renderHtml(itemsDataView[i].Notes)+'</td>'+
                '<td>'+itemsDataView[i].cntOrdersToDemand+'/'+ itemsDataView[i].relevantStock+'</td>'+
                '<td>'+$scope.getShelf(itemsDataView[i])+'</td>'+
                '<td class="balance">'+$scope.renderHtml($scope.getBal(itemsDataView[i].Docbal))+'</td>'+
              '</tr>';
    }
    callBack (tr);
}

0 个答案:

没有答案