Hello,
Am 17.07.12 04:07, schrieb Shane Harter:
Well, it really depends on your individual application and its models.
That’s why Chaplin doesn’t provide a built-in solution. I’ve written a
longer piece on this:
https://github.com/chaplinjs/chaplin/issues/120#issuecomment-6406983
There are probably several types of models and collections in your
application. They usually differ in several aspects:
- How much data they hold
- How often they are loaded and accessed
- How often they change on the server, do they change incrementally
- How important they are in the user flow, whether the user flow can
benefit from caching
- etc.
Depending on these criteria it’s either easy and beneficial to cache the
models on the client side, or it’s rather hard and problematic.
Some examples:
- The logged-in user model. Usually there is just one. It is loaded once
per session and doesn’t hold much data itself. It’s needed virtually
everywhere. Rarely changed on the server side while using the app.
-> It’s safe to cache it as Backbone model in memory as long as the app
runs.
- A collection with fixed categories (like a navigation tree). Loaded
once, pretty much data in total, accessed frequently. Doesn’t change
during the session.
-> Load with app start, hold in memory infinitely.
- A collection of articles on the home page. Accessed quite often during
a session. Much data. Changes often on the server side because new
articles come in.
-> It’s not necessary to hold it in memory as a JavaScript object. But
it does make sense to use HTTP caching properly with a reasonable
expiry. The resource is read from the browser cache the second time,
only the Backbone collection is created from scratch.
- A single article. Accessed once or probably twice. Few data. Rare changes.
-> Don’t cache in memory, rather use HTTP caching.
Sometimes it’s better to hold collections and models in memory to
improve the user experience. For example, the user is reading the
article list at /articles. This list may already contain the full
articles. Clicking on an article should immediately show the full
content at /articles/123 without fetching JSON data from the server.
Most likely the user will return to /articles by using the browser’s
back button. In this case the list view should render immediately.
In this scenario it makes sense to hold the collection in memory as long
as the user stays in this loop. When the user leaves this context, the
list can be purged.
I’m explaining this in-depth to answer how and where to store the
models. It mostly depends on the aspects mentioned above.
In Chaplin, the mediator can be used to store central models like the
user. Just create a property before it’s sealed (in case you seal it,
the example apps do so).
mediator.user = null
Later you may fill it:
mediator.user = new User()
and access it by requiring the mediator module.
See the Facebook app for instance:
https://github.com/chaplinjs/facebook-example
If you want to cache all models of a type since the end of the session,
you can create a hash on the model constructor (CoffeeScript example code):
class Article extends Model
# Static properties/methods
@instances: {}
@find: (id) ->
Article.instances[id] or= new Article {id}
To get an article, you may call Article.find(123).
This is a very simple caching concept with no limit. An alternative
would be an array which just holds the last 10 instances:
class Article extends Model
# Static properties/methods
@instances: []
@find: (id) ->
# Cache lookup
article = _.find Article.instances, (article) ->
article.id is id
unless article
article = new Article {id}
# Add to cache
Article.instances.unshift article
# Trim cache
Article.instances = Article.instances.slice 0, 10
article
The same way a model or collection can be saved at a controller
constructor. This is the scenario I’ve described above:
class ArticlesController extends Controller
@collection: null
index: ->
# Don’t save on instance, but on constructor
ArticlesController.collection = new Articles()
# Show list view…
show: (params) ->
article = ArticlesController.collection.get
params.id
unless article
article = new Article {id}
ArticlesController.collection.add article
# Show article detail view…
# Chaplin passes the name of the new controller to the dispose
# method so it can decide whether to dispose
dispose: (params, newControllerName) ->
if newControllerName isnt 'articles'
ArticlesController.collection.dispose()
delete ArticlesController.collection
super
This demonstrates how the collection is removed when another controller
takes over. Changing from the index action to show and back won’t remove
the collection.
Just let me know if you got further questions.
Regards,
Mathias