The data module invent a DSL for querying complex JavasScript Object graph both from server and on the client, along with the associated data structures for caching queried objects.
TroopJS query is built on an object graph implemented by data/cache/component
, are essentially weakly referenced standalone objects living in a big cache pool, referencing others only by an unique id,
by utilizing weak references, we're able to serialize the entire graph into big flatten JavaScript array that retains all the referenced objects:
Two objects, both have an unique id that is consisted of a resource type and an identifier, e.g. user!troopjs
or profile!0
.
user
object is referencing it's profile by a collapsed object with the profile id, when querying for the user object, say, from server, it is possible that user is only interested in user's "email"
rather than the profile, making the profile
property optionally expandable, in this way payload on the wire is significantly reduced, eventually allowing the client to re-assemble properties on demand:
It is an important consideration that Object Graph is of plain old JavaScript objects without imposing any intermediate data structure, this makes it extremely easy for consumption, blazing fast and is future proof with data binding by Object.observe. expiration is by adding a few additional meta properties, even granular cache control for each objects is feasible.
With object graph defined above, a tiny DSL is invented to pull objects out of the graph, like user!troopjs.repos.troopjs-core.pulls,.followers@2:3
, which syntax is consist of the following components:
user
troopjs
repos.troopjs-core
.followers
2:3
Then query API is a hub service provided by under the query
topic which is implemented by data/query/component
, returning a promise that resolves to a list of the queried values:
When performing a query, what TroopJS does is much more than simply sending the query to the server, instead it tries best to reduce the query from what we have on the client:
In the above example, if you have queried for user!troopjs.repos
moments ago, this object will be returned immediately served from cache, eliminating the need for querying the server again, a significant benefit coming from the
fact that since cache reducing is transparent for the query service, mock server communication is as simple as populating the cache:
The GC is an optional optimization service provided by data/cache/service
that take cares of de-referencing any expired objects from cache to free out memories, it implements a generation-based algorithms for efficiently determinate
expired objects, each GC run should have very little impact on performance. The GC will be running automatically as soon as the service is started.
The built-in cache component is memory-based, but it's fairly easy to implement a cache component powered by persisted storage, as an example for landing cache in local storage, checkout opt/store/component
and
contrib-browser/contrib-browser/store/adapter/local
for details.
Find an error? Let us know →