I want to cache the result of a query in ember-data. (findQuery
)
To make it clear: I don't want to cache the entire models; just what models are the result of the query. Where is the right place for this?
I was thinking about implementing this in the adapter and cache the result of the AJAX call, but I don't think this is a good solution since I don't wanna override the loaded and maybe newer and/or modified model data.
I don't thinks its possible to just return a list of ID's, and to manipulate the adapter and the serializer for this simple use-case seems to be messy!
Actually I don't want that findQuery
is called for specific types of querys. Like the behavior of findAll
. Nice would be something like a queryShouldBeCached
hook.
Is there a good Solution for this?
The most important thing to know is that Ember. js is completely backend-agnostic. You could write this part just as well in Ruby, PHP, Python or any other server language.
The store contains all of the data for records loaded from the server. It is also responsible for creating instances of Model that wrap the individual data for a record, so that they can be bound to in your Handlebars templates.
In Ember Data, models are objects that represent the underlying data that your application presents to the user. Note that Ember Data models are a different concept than the model method on Routes, although they share the same name.
I'm not an Ember expert but I think you can address your problem with a pure JS solution.
Given Ember Data queries return Promises, e.g. return this.store.findAll('blog-post'); // => Promise
, we can cache promises in a simple object with higher order functions (functions that return functions). The object cache could be replaced with localStorage
, sessionStorage
, Map
or even WeakMap
but I'm using the object cache to make things simple to understand.
What you want to essentially do is to replace following call:
return this.store.findAll('blog-post');
with something more or less like:
return cachedStore.findAll('blog-post');
actually, with the solution below it might look more like:
return cachedStore.call(this, 'findAll', 'blog-post');
As a result, you will request data once and always return from cache in subsequent calls.
Let me show you how the implementation might look like:
var cachedStore = (function () {
// Your cache - in this case simple object literal
var cache = {};
// Actual method that will check cache for results before trying to query services
return function (method) {
var args = Array.prototype.slice.call(arguments, 1);
var serializedArgs = JSON.stringify(args);
if (!(serializedArgs in cache)) {
cache[serializedArgs] = this.store[method].apply(this, args);
}
return cache[serializedArgs];
};
}());
And here's a sample usage:
// Fires a request
cachedStore.call(this, 'findAll', 'blog-post');
// Returns from cache
cachedStore.call(this, 'findAll', 'blog-post');
// Returns from cache
cachedStore.call(this, 'findAll', 'blog-post');
// Fires a request
cachedStore.call(this, 'findRecord', 'blog-post', 123);
// Returns from cache
cachedStore.call(this, 'findRecord', 'blog-post', 123);
// Returns from cache
cachedStore.call(this, 'findRecord', 'blog-post', 123);
Does that help in any way?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With