2013-04-03 7 views
6

Ho una classe chiamata Articolo filtrato da PeriodId. Ci sono molti periodi - ma dobbiamo solo guardare uno alla volta. Voglio presentare all'utente un caricamento iniziale dei dati (diciamo dove PeriodId == 1). Quindi voglio che l'utente sia in grado di interrogare/filtrare su altri periodi.Breezejs - modello per interrogare la cache locale

Se l'utente seleziona PeriodId == 2, voglio che entityManager interroghi la cache locale e, se i dati sono presenti, restituisci tali dati. Se non si trova nella cache locale, desidero interrogare il server e aggiungere il set in cui PeriodId == 2 alla cache. Se l'utente fa clic su PeriodId == 1, tali dati dovrebbero già essere nella cache e non round-trip sul server.

Utilizzando il codice qui sotto, sto colpendo il server ogni volta che seleziono un punto (anche se si passa avanti e indietro). C'è un modello che risolve questo ... NON conosco le chiavi primarie qui.

var getItems = function (myObservable, periodId, forceRemote) { 

    var pId = periodId ? periodId : 1; 

    var query = entityQuery.from('Item') 
     .orderBy(orderBy.items) 
     .where("PeriodId", "==", pId); 

    if (!forceRemote) { 
     var r = getLocal(query); 
     if (r) { 
      if (r.length > 3) { 
       myObservable(r); 
       return Q.resolve(); 
      } 
     } 
    } 

    return manager.executeQuery(query) 
     .then(querySucceeded) 
     .fail(queryFailed); 

    function querySucceeded(data) { 
     if (myObservable) { 
      myObservable(data.results); 
     } 
    } 
}; 

function getLocal(query) { 
    try { 
     return manager.executeQueryLocally(query); 
    } catch(e) { 
     // set was not found in local cache, return null - forcing trip to server 
     return null; 
    } 
} 

UPDATE:

Incorporando il suggerimento di Jay, (ho dovuto rinominare 'param' a 'pId', 'q' per 'query', azzerare il queryParamCache se forceRemote == true, e ho dovuto anteporre la FetchStrategy con) 'gioco da ragazzi.':

var queryParamCache = {}; 

var getItems = function(myObservable, periodId, forceRemote) { 

    if (forceRemote) { 
     queryParamCache = {}; 
    } 

    var pId = periodId ? periodId : 1; 

    var query = entityQuery.from('Item') 
     .orderBy(orderBy.items) 
     .where('PeriodId', '==', pId); 

    var isInCache = queryParamCache[pId]; 

    if (isInCache && !forceRemote) { 
     query = query.using(breeze.FetchStrategy.FromLocalCache); 
    } else { 
     queryParamCache[pId] = true; 
     query = query.using(breeze.FetchStrategy.FromServer); 
    } 

    return manager.executeQuery(query) 
     .then(querySucceeded) 
     .fail(queryFailed); 

    function querySucceeded(data) { 
     rosterObservable(data.results); 
    } 
}; 

function queryFailed(error) { 
    var msg = 'Error retreiving data. ' + error.message; 
    logError(msg, error); 
    throw error; 
} 

risposta

6

un'idea più semplice potrebbe essere proprio di cache fatto sul fatto che è stata eseguita la query oppure no. E invece di usare il metodo executeQueryLocally, in questo caso è più facile usare la possibilità di specificare una FetchStrategy . Si noti che quando si utilizza FetchStrategy.FromLocalCache si otterrà comunque una promessa restituita, ma tale promessa verrà effettivamente eseguita immediatamente. La parte bella è che non devi trattare le query remote vs local in modo diverso.

var queryParamCache = {}; 
var getItemsPromise = function (periodId, forceRemote) { 

    var pId = periodId ? periodId : 1; 

    var query = entityQuery.from('Item') 
     .orderBy(orderBy.items) 
     .where("PeriodId", "==", pId); 


    var isInCache = queryParamCache[pId]; 
    if (isInCache && !forceRemote) { 
     q = q.using(FetchStrategy.FromLocalCache); 
    } else { 
     queryParamCache[pId] = true; 
     q = q.using(FetchStrategy.FromServer); 
    } 
    return manager.executeQuery(q); 
} 

L'altra caratteristica di questo approccio è che si occupa anche il caso in cui la query "a distanza" non restituisce alcun record. Quindi, a differenza del test per verificare se la query locale restituisce effettivamente i dati, che sarà falso sia quando non hai ancora eseguito la query e quando non ci sono dati che soddisfano la query, questo approccio tiene semplicemente traccia di se hai mai eseguito la query, indipendentemente dai suoi risultati.

+0

Brillante, Jay! Qualche modifica e ha funzionato ... aggiornerò la mia domanda con le modifiche apportate. Grazie! – Kevin