Backbone.Hoard

XHR Consolidation and Caching

for Backbone.js

Christian Maher / @christiansmaher

cmaher.github.io/backbone.hoard/slides

Use Cases

  • Dashboard Applications (XHR Consolidation)
  • Route-Specific Data (Caching)

What does this look like?

Dashboard Applications

/models
/models/1
/models/2
/models/3

Dashboard Applications

/models
/models/1
/models/1
/models

Dashboard Applications

/models
/models
/models
/models

XHR Consolidation

Prevent multiple simultaneous requests to the same endpoint

XHR Consolidation

Setup Hoard
var cacheControl = new Backbone.Hoard.Control();
var MyModel = Backbone.Model.extend({
  url: function () { return '/models/' + this.id; },
  sync: cacheControl.getModelSync()
});

var model1 = new MyModel({ id: 1 });
var model2 = new MyModel({ id: 1 });

XHR Consolidation

In Action
Promise.all([model1.fetch(), model2.fetch()]).then(function () {
  // only 1 ajax request has been made
  doStuff();
});

Route-Specific Data

/users

Route-Specific Data

/users/1

Christian (now)

Following

Route-Specific Data

/users/2

Route-Specific Data

/users/3

Caching

Prevent a request to an endpoint if that endpoint has been requested before

Caching Route-Specific Data

Without Hoard

var routePromise;
var model = collection.get(modelId);
if (model) {
  routePromise = Promise.resolve();
} else {
  model = new MyModel({ id: modelId });
  collection.add(model);
  routePromise = model.fetch();
}
routePromise.then(function () {
  doRoute(model);
});

Caching Route-Specific Data

With Hoard

var model = new MyModel({ id: modelId });
model.fetch().then(function () {
  doRoute(model);
});

What About...

  • Dependency Injection
  • Existing Backbone Plugins
  • HTTP Headers

Dependency Injection

  • Complicated events
  • Imperfect key generation
  • Multiple fetches on change

Existing Backbone Plugins

  • backbone-fetch-cache
  • backbone.cachingSync

HTTP Headers

  • cache-control
  • etag

Advanced Use Cases

  • Key Manipulation and Interpretation
  • Chunky Endpoints

Key Interpretation

  • Good RESTful APIs establish patterns

    • ?page=5
    • ?offset=100
    • ?filter="odd_id"
    • ?ids=1,2,3
  • Developers can capture those patterns on the client

Key Interpretation

var coll = new MyCollection({ url: '/models' });
var filtered = new MyCollection({ url: '/models?filter="odd_id"' });
Promise.all([coll.fetch(), filtered.fetch()]).then(function () {
  // Only 1 ajax request has been made
  // coll has all models
  // filtered has all models with odd ids
});

Chunky Endpoints

  • Contain potentially unrelated data
  • Require processing
  • Can be processed in different ways

Chunky Endpoints

// response from /data.json
{
  "a": 1,
  "b": 2,
  "c": 3,
  // ...
}

Chunky Endpoints

var ChunkModel = Backbone.Model.extend({
  url: '/data.json',
  sync: cacheControl.getModelSync()
});

var ModelOne = ChunkModel.extend({
  parse: function (data) {
    return { calculated: data.a + data.b }
  }
});

var ModelTwo = ChunkModel.extend({
  parse: function (data) {
    return { calculated: data.b * data.c }
  }
});

Links