2012-11-28 9 views
6

La domanda: Come posso strutturare il mio codice in modo che le associazioni ad eliminazione diretta non vengono applicate fino a quando tutte le query per il ViewModel sono stati eseguiti?knockout.js applybindings dopo query brezza js completati

Aggiornamento: Dopo ulteriori ricerche e sperimentazione, penso che utilizzare qualcosa sulla falsariga di una funzione differita possa funzionare. Ho provato alcune implementazioni, tuttavia rimuove solo fino al richiamo della query, piuttosto che fino a quando tutti i risultati della query non sono stati elaborati. Ovviamente sto facendo qualcosa di sbagliato qui, ma il mio javascript foo è debole.

tecnologie utilizzate: Entity Framework 5 w/Oracle, .Net 4 Web API, Knockout 2.2, Breeze 0.71.3

La situazione: Breeze viene utilizzato per chiamare un metodo Web API che recupera un Enumerable di POCOs, popola una matrice osservabile a eliminazione diretta e l'array è associato a un controllo selezionato nella vista.

Il problema: Le query di brezza non sono state completate e gli osservabili a eliminazione diretta non sono stati compilati prima di applicare i collegamenti ViewModel alla vista. Quando vengono restituiti i risultati della query, l'interfaccia utente non risponde per 5 - 7 secondi mentre il ko osservabile viene popolato e quindi il controllo di selezione viene aggiornato. Sulla base della registrazione di questo sembra essere il problema ...

Il file 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 è il mio ViewModel file JavaScript. Ecco un metodo di essere esposti a exec una query:

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

Ecco la query brezza dataservice.js di file:

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

risposta

5

Qualche considerazione mi vengono in mente:

  1. I raramente spinge uno per uno nell'array osservabile . Troppi aggiornamenti DOM. Creare invece una matrice temporanea e aggiornare l'array osservabile con quello. Credo che questa sia la risposta al problema di prestazioni che stai chiedendo.

  2. Impostare un inizializzare il metodo che restituisce una promessa quando tutti i metodi di caricamento asincrono iniziali sono completi.

  3. ritardo ko.applyBindings fino alla inizializzare promessa si risolve con successo.

  4. Considerare di mostrare uno splashscreen + spinner mentre si attende l'inizializzazione.

  5. Cerca di non fare troppo durante l'inizializzazione.

Non riesco a mostrarvi come fare ognuna di queste cose in questa risposta. Ti mostrerò il numero 1 e ti rimanderò "Fetch on Launch" nella documentazione per # 2. Ricerca web + sperimentazione sono i tuoi amici per il resto.

Aggiorna observableArray con una serie
 
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); 
     } 

mi piace usare l'ECMAScript 5 Array.map sintassi che restituisce un array dopo applicando una funzione ad ogni elemento di una matrice di origine. Quindi scriverei:

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

Questo ha risolto il problema in modo assoluto! La matrice temporanea ha fatto il trucco. Inoltre, grazie per la risposta completa, altri suggerimenti e risorse. Ho appena iniziato con knockout e brezza e non vedo l'ora di imparare il modo corretto per strutturare queste applicazioni. Il javascript può sfuggire di mano rapidamente. –

+0

Capisco perfettamente :) Potrebbe non essere necessario il materiale RequireJS. Mi piace molto. Ma è avanzato e molte app possono andare d'accordo con un modello di modularità meno sofisticato (ad esempio, "Revealing Module"). Puoi tornare da lì a Require senza un grande sforzo. In bocca al lupo! – Ward

Problemi correlati