2012-09-06 2 views
2

약 1100 개의 레코드가 있습니다. 이 데이터 세트는 관측 가능한 배열로 매핑되고이 관측 가능한 배열은 뷰에 바인딩됩니다. 이러한 레코드는 자주 업데이트되므로 ko.mapping.fromJS 도우미를 사용하여 항상 관찰 가능 어레이가 업데이트됩니다.녹아웃 매핑 플러그인의 성능 문제가 발생했습니다

이 특정 명령은 모든 행을 처리하는 데 약 40 초가 걸립니다. 사용자 인터페이스는 해당 기간 동안 잠글뿐입니다.

var transactionList = ko.mapping.fromJS([]); 

//Getting the latest transactions which are around 1100 in number; 
var data = storage.transactions(); 

//Mapping the data to the observable array, which takes around 40s 
ko.mapping.fromJS(data,transactionList) 

해결 방법이 거기에가 - 여기

코드인가? 아니면 공연을 개선하기 위해 웹 작업자를 선택해야합니까?

답변

0

지도 플러그인과 동일한 문제가있었습니다. 녹아웃 팀 (Knockout team)은 매핑 플러그인이 대형 어레이에서 작동하지 않는다고 말합니다. 페이지에 큰 데이터를로드해야하는 경우 부적절한 시스템 설계가있을 수 있습니다.

가장 좋은 방법은 페이지로드시 모든 데이터를로드하는 대신 서버 페이지 매기기를 사용하는 것입니다. 당신이 응용 프로그램의 설계를 변경하지 않으려면 아마도 당신을 도울 몇 가지 해결 방법이 있습니다 : 비동기

var data = storage.transactions(); 
var mappedData = ko.utils.arrayMap(data , function(item){ 
    return ko.mapping.fromJS(item); 
}); 

var transactionList = ko.observableArray(mappedData); 
  • 지도 배열 수동

    1. 지도 배열. 나는 다른 스레드에 부분에 의해 배열을 처리하는 기능을 작성하고 보고서는 사용자에게 진행 :

      function processArrayAsync(array, itemFunc, afterStepFunc, finishFunc) { 
          var itemsPerStep = 20; 
      
          var processor = new function() { 
           var self = this; 
           self.array = array; 
           self.processedCount = 0; 
           self.itemFunc = itemFunc; 
           self.afterStepFunc = afterStepFunc; 
           self.finishFunc = finishFunc; 
           self.step = function() { 
            var tillCount = Math.min(self.processedCount + itemsPerStep, self.array.length); 
            for (; self.processedCount < tillCount; self.processedCount++) { 
             self.itemFunc(self.array[self.processedCount], self.processedCount); 
            } 
      
            self.afterStepFunc(self.processedCount); 
            if (self.processedCount < self.array.length - 1) 
             setTimeout(self.step, 1); 
            else 
             self.finishFunc(); 
           }; 
          }; 
      
          processor.step(); 
      }; 
      

    귀하의 코드 :

    var data = storage.transactions(); 
    var transactionList = ko.observableArray([]); 
    
    processArrayAsync(data, 
        function (item) { // Step function 
         var transaction = ko.mapping.fromJS(item); 
         transactionList().push(transaction); 
        }, 
        function (processedCount) { 
         var percent = Math.ceil(processedCount * 100/data.length); 
         // Show progress to the user. 
         ShowMessage(percent); 
        }, 
        function() { // Final function 
         // This function will fire when all data are mapped. Do some work (i.e. Apply bindings). 
        }); 
    

    는 또한 대체 매핑 라이브러리를 시도 할 수 있습니다 : knockout.wrap를. 플러그인 매핑보다 빠릅니다.

    두 번째 옵션을 선택했습니다. 다음과 같이 나 또한 해결의 생각

  • +0

    매우 흥미로운 솔루션입니다. 얼마나 빨리 JsPerf를 만들면 재미 있을지 알 수 있습니다. – billy

    +0

    @billy 게시물을 편집 할 때주의하십시오. 원래 질문의 코딩 스타일을 변경하는 것은 게시물의 의미를 변경하는 것과 동일하게 간주됩니다. 나는 편집을 롤백했다. – Lundin

    +0

    다음은 jsperf입니다. http://jsperf.com/ko-view-model-vs-ko-mapping-complex-viewmodel-creation/28 (테스트중인 커스텀 매퍼의 저자입니다) –

    0

    , 이것은 코드 -

    var transactionList = ko.mapping.fromJS([]); 
    
    //Getting the latest transactions which are around 1100 in number; 
    var data = storage.transactions(); 
    
    //Mapping the data to the observable array, which takes around 40s 
    // Instead of - ko.mapping.fromJS(data,transactionList) 
    var i = 0; 
    
    //clear the list completely first 
    transactionList.destroyAll(); 
    
    //Set an interval of 0 and keep pushing the content to the list one by one. 
    var interval = setInterval(function() {if (i == data.length - 1) { 
                 clearInterval(interval);} 
    
                transactionList.push(ko.mapping.fromJS(data[i++])); 
               }, 0); 
    
    1

    Knockout.viewmodel의 적은 양을 사용하는이 같은 큰 개체 배열 viewmodels을 만들기에 상당히 빠른 knockout.mapping에 대한 대체입니다. 상당한 성능 향상이 나타납니다.

    http://coderenaissance.github.com/knockout.viewmodel/

    +0

    실제로 성능을 향상시킬 수 있는지 알아보십시오. 필자의 경우에 어떻게 사용할 수 있는지 묘사하기위한 샘플 코드를 제공해 주시겠습니까? – Tushar

    0

    매핑이 마법이 아닙니다. 대부분의 경우이 단순 재귀 함수는 충분할 수

    function MyMapJS(a_what, a_path) 
    { 
        a_path = a_path || []; 
    
        if (a_what != null && a_what.constructor == Object) 
        { 
         var result = {}; 
         for (var key in a_what) 
          result[key] = MyMapJS(a_what[key], a_path.concat(key)); 
         return result; 
        } 
    
        if (a_what != null && a_what.constructor == Array) 
        { 
         var result = ko.observableArray(); 
         for (var index in a_what) 
          result.push(MyMapJS(a_what[index], a_path.concat(index))); 
         return result; 
        } 
    
        // Write your condition here: 
        switch (a_path[a_path.length-1]) 
        { 
         case 'mapThisProperty': 
         case 'andAlsoThisOne': 
          result = ko.observable(a_what); 
          break; 
         default: 
          result = a_what; 
          break; 
        } 
        return result; 
    } 
    

    코드 위 mapThisProperty과 오브젝트 계층의 모든 레벨에서 andAlsoThisOne에서 관찰 가능한 특성을 만든다; 다른 속성은 일정하게 유지됩니다. 값이있는 수준 (깊이)의 경우 a_path.length을 사용하거나 a_path의 더 많은 요소를 사용하여보다 복잡한 조건을 표현할 수 있습니다.당신은 상태 a_what 대해서 typeof를 사용할 수 있습니다

    if (a_path.length >= 2 
        && a_path[a_path.length-1] == 'mapThisProperty' 
        && a_path[a_path.length-2] == 'insideThisProperty') 
        result = ko.observable(a_what); 
    

    , 예를 들면 : 예를 들어, 모든 끈을 관찰 할 수있게 만드는 것. 일부 속성을 무시하고 특정 속성을 새로 추가 할 수 있습니다. 또는 a_path을 생략 할 수도 있습니다. 등

    는 장점은 다음과 같습니다

    • 사용자 정의 (더 쉽게 이상의 knockout.mapping을).
    • 충분히 짧으면 복사하여 붙여 넣고 필요한 경우 다른 개체에 대한 개별 매핑을 작성하십시오.
    • 작은 코드, knockout.mapping-latest.js은 (는) 페이지에 포함되지 않습니다.
    • 절대적으로 필요한 것보다 빠를 수 있어야합니다.
    관련 문제