Knockout.js applies bindings after completing js breeze requests

Question: How can I structure my code so that knockout bindings are not applied until all requests for the ViewModel are completed?

Update:. After some further research and experimentation, I think that using something in accordance with the snooze function may work. I tried several implementations, however, it only postpones the request until the request is called, and not until all the results of the request have been processed. I obviously am doing something wrong, but my javascript foo is weak.

Used technologies: Entity Framework 5 w / Oracle, .Net 4 Web API, knockout 2.2, breeze 0.71.3

Situation: A breeze is used to invoke a Web API method that extracts an Enumerable from POCOs, populates the observable array with a knockout, and the array is bound to a select control in the view.

Problem: Breeze requests were not completed, and observed knockouts were not filled before the ViewModel bindings on the view were applied. When the query results are returned, the user interface does not respond for 5-7 seconds, and the ko-observable is populated, and thus the selection control is updated. Based on the registration, this seems to be the problem ...

Cshtml file:

<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 is my javascript ViewModel file. The method that executes the request is called here:

 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)); }, 

Here is the breeze request from dataservice.js file:

 function getBrokers() { var query = new entityModel.EntityQuery() .from("GetBrokers") //.orderBy("name"); return manager.executeQuery(query); }; 
+6
source share
1 answer

A few thoughts come to me:

  • I seldom fits one after another in an observable array . Too many DOM updates. Create a temporary array and update the observed array. I believe this is the answer to the performance problem you are asking for.

  • Configure an initialization method that returns a promise when all of the original asynchronous loading methods are complete.

  • Delay ko.applyBindings until the promise of initialization is successfully resolved.

  • Consider displaying a splash screen with a + screen extension while you wait for initialization to complete.

  • Try not to do too much during initialization.

I cannot show you how to do all this in this answer. I will show you No. 1 and tell you " Fetch on Launch " in the documentation for # 2. Web search + experiment are your friends for the rest.

Update observed array with array
  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);
         }

I like to use the ECMAScript 5 Array.map syntax, which returns an array after applying the function to each element of the original array. Therefore, I would write:

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

All Articles