2012-11-28 32 views
6

問題:如何構造我的代碼,以便在ViewModel的所有查詢都已執行之前不會應用挖空綁定?微風js查詢完成後knockout.js applybindings

更新:經過一些進一步的研究和實驗後,我認爲沿着延遲函數行使用某些東西可能會奏效。我已經嘗試了一些實現,但它只是在調用查詢之前才推遲,而不是直到處理完所有查詢結果。我顯然在這裏做錯了什麼,但我的JavaScript foo很弱。使用

技術:實體框架5W /甲骨文,.NET 4的網頁API,敲除2.2,微風0.71.3

的情況:微風被用於調用以檢索一個Web API方法一個可枚舉的POCO,填充一個可挖掘的可觀察數組,並且該數組綁定到View中的一個選擇控件。

問題:微風查詢尚未完成,並且在將ViewModel綁定應用於視圖之前,挖空觀測數據尚未填充。當查詢結果返回時,UI在5-7秒內沒有響應,而ko observable被填充,因此選擇控件被更新。 基於日誌這似乎是問題...

的CSHTML文件:

<select data-bind="options: $root.brokers, value: 'id', optionsText: 'name'"> 
<script data-main="/BrokerCommission/Scripts/app/main" src="/BrokerCommission/Scripts/require.js"></script> 

main.js:

requirejs.config(
    { 
     // well-know paths to selected scripts 
     paths: { 
      'breeze': '../breeze.debug', // debug version of breeze 
      'text': '../text'// html loader plugin; see http://requirejs.org/docs/api.html#text 
     } 
    } 
); 

define(['logger', 'text', 'breeze'], function(logger) { 

require(['vm.muni'], 
function() 
{ 
    logger.info('applying bindings'); 
    ko.applyBindings(my.vm); 
}); 

vm.muni是我的ViewModel javascript文件。這裏有被暴露給exec查詢的方法:

getAllBrokers = function() { 
     dataservice.getBrokers() 
      .then(processBrokerQueryResults) 
      .fail(handleQueryErrors); 
    }, 

    processBrokerQueryResults = function (data) { 
     logger.info("Start loading Brokers " + Math.round(new Date().getTime()/1000)); 
     my.vm.brokers([]); 
     $.each(data.results, function (i, d) { 
      brokers.push(new my.Broker() 
       .id(d.id) 
       .name(d.name) 
      ); 
     }); 
     logger.info("End loading Brokers " + Math.round(new Date().getTime()/1000)); 
    }, 

這裏是dataservice.js文件微風查詢:

function getBrokers() { 
    var query = new entityModel.EntityQuery() 
      .from("GetBrokers") 
      //.orderBy("name"); 
    return manager.executeQuery(query); 
}; 

回答

5

的一點想法發生對我說:

  1. 很少一個一個地推入observableArray。太多的DOM更新。改爲創建一個臨時數組,並用此更新observableArray。我相信這是您所問的性能問題的答案。

  2. 設置初始化當所有初始異步加載方法完成時返回承諾的方法。

  3. 延遲ko.applyBindings直到初始化承諾成功解析。

  4. 考慮在等待初始化完成時顯示splashscreen + spinner。

  5. 儘量不要在初始化時做太多。

我不能告訴你如何去做這個答案中的每一件事。我會在這裏向您展示#1,並在#2的文檔中提及您「Fetch on Launch」。網絡搜索+實驗是其餘的朋友。

更新 observableArray以與陣列
 
processBrokerQueryResults = function (data) { 
     ... 
     var tempArray = [] 
     $.each(data.results, function (i, d) { 
      tempArray.push(dtoToBroker(d)); 
     }); 
     brokers(tempArray); 
     ... 

     // I prefer named fns to long lambdas 
     function dtoToBroker(dto) { 
      return new my.Broker() 
        .id(d.id) 
        .name(d.name); 
     } 

我喜歡用的ECMAScript 5 Array.map語法,將函數應用於源陣列的每個元素之後返回一個數組。所以我會寫:

 
processBrokerQueryResults = function (data) { 
     ... 
     brokers(data.results.map(dtoToBroker)); 
     ... 
} 
+0

這絕對解決了這個問題!臨時數組做到了。此外,感謝您的徹底迴應,其他技巧和資源。我只是開始了淘汰賽和微風,並期待着學習正確的方式來構建這些應用程序。 JavaScript可以快速失控。 –

+0

我完全理解:)你可能不需要RequireJS的東西。我很喜歡。但它是先進的,許多應用程序可以用不太複雜的模塊化模式(例如「顯示模塊」)相處得很好。您無需付出巨大的努力就可以從那裏回到需求。祝你好運! – Ward