Request a local cache before requesting a server in Breeze JS

I have an application using Breeze to request data. I want to check the local cache first and then the server cache if the results do not return (I followed the Jumpstart course from John Papa SPA). However, I found a flaw in my logic, and I'm not sure how to fix it. Assuming I have 10 elements that match my query.

Situation 1 (which works): I go to the list page (Page A) that displays all 10. The hit server as a cache is empty and adds all 10 to the cache. Then go to the page displaying 1 result (Page B), which is in the cache. So all is well.

Situation 2 (problem): I go to a page displaying 1 record first (Page B). Then I go to the list page (Page A), which checks the cache and finds 1 entry, and because of this line ( if (recordsInCache.length > 0) ) it goes out and displays only one entry.

For some reason I need to know that on the server (9) there are no more entries that are NOT in the cache, i.e. the general records for this request are actually 10, I have 1, so I have to hit the server for the remaining 9.

Here is my request for page A:

 function getDaresToUser(daresObservable, criteria, forceServerCall) { var query = EntityQuery.from('Dares') .where('statusId', '!=', enums.dareStatus.Deleted) .where('toUserId', '==', criteria.userId) .expand("fromUser, toUser") .orderBy('deadlineDate, changedDate'); return dataServiceHelper.executeQuery(query, daresObservable, false, forceServerCall); } 

and here is my request for page B (separate element)

 function getDare(dareObservable, criteria, forceServerCall) { var query = EntityQuery.from('Dares') .expand("fromUser, toUser") .where('dareId', '==', criteria.dareId); return dataServiceHelper.executeQuery(query, dareObservable, true, forceServerCall); } function executeQuery(query, itemsObservable, singleEntity, forceServerCall) { //check local cache first if (!manager.metadataStore.isEmpty() && !forceServerCall) { var recordsInCache = executeLocalQuery(query, itemsObservable, singleEntity); if (recordsInCache.length > 0) { callCompleted(); return Q.resolve(); } } return manager.executeQuery(query) .then(querySucceeded) .fail(queryFailed); 

}

 function executeLocalQuery(query, itemsObservable, singleEntity) { var recordsInCache = manager.executeQueryLocally(query); if (recordsInCache.length > 0) { processQueryResults(recordsInCache, itemsObservable, singleEntity, true); } return recordsInCache; } 

Any advice appreciated ...

+4
source share
2 answers

If you just want to hit the server for comparison purposes, then at some point (either when downloading the application, or when you get to the list page), call inlineCount to compare everything on the server with what you already saw in this answer stackoverflow.com/ questions / 16390897 / counts-in-breeze-js / ...

The way you can use this creatively while you are requesting a single entry would be this:

Set some variable in your view model or somewhere equal to the total score

 var totalCount = 0; 

When you request a single entry, get a built-in counter -

 var query = EntityQuery.from('Dares') .expand("fromUser, toUser") .where('dareId', '==', criteria.dareId) .inlineCount(true); 

and set totalCount = data.inlineCount; The same when you get a list of common elements, just set totalCount to inlineCount so you always know if you have all the entities.

+1
source

I thought about this problem more last year (and since then moved from Durandal + Breeze to Angular + Breeze: In Angular, you can easily cache a service call using

 return $resource(xyz + params}, {'query': { method:'GET', cache: true, isArray:true }}).query(successArrayDataLoad, errorDataLoad); 

I think Angular caches parameters this request and knows when it is already there. Therefore, when I switch this method to using Breeze, I lose this functionality, and all my List calls are pushed every time.

So the real problem is the List . Single entities can always check the local cache, and if nothing returns, check the server (because you expect exactly 1).

However, the list data depends on the parameters. For example, if I have a GetGames call that takes in CreateByUserId, every time I supply a new CreateByUserId, I need to return to the server.

So, I think what I really need to do here to cache my List calls is to cache a key for each call, which is a combination of QueryName and Params.

For example, GetGames1 for UserID 1, and then GetGames2 for UserId 2.

The logic would be: check the Angular cache to see if this call was previously made in this session. If so, check the local cache first. If nothing returns, check the server.

If this is not the case, check the server as a local cache. You can have some data in it for this request, but it is not guaranteed to be a complete set.

The only other way is to hit the server each time to get a counter for this Query + Params, and then get into the local cache and compare the counter, but this is more inefficient.

Thoughts?

0
source

Source: https://habr.com/ru/post/1496542/


All Articles