Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Backbone Tango: Dancing with geographical data

The Backbone Tango: Dancing with geographical data

Using Backbone as the core of our geo app has been a blessing in many ways. But working with large amounts of geographical data also presents some challenges. This session will shine a light on the ways we extended Backbone to solve some of them.

Topics that will be covered:

* Handling large amounts of geographical data
* Spatial indexing for a fast cache
* Lazy loading Collections and Models
* Grouping multiple requests into one
* Keeping track of failed HTTP requests across sessions

Avatar for Daan Mortier

Daan Mortier

December 16, 2014

Other Decks in Programming

Transcript

  1. 1

  2. 1 2

  3. 1 2

  4. var MapKit.Collection = Backbone.Collection.extend({ initialize: function() { this.tileIndex = {};

    this.on('add', this._addIndexEntry, this); this.on('remove', this._removeIndexEntry, this); }, _addIndexEntry: function( model, collection, options ) { var tileId = model.get('tile_id'); this.tileIndex[tileId].models.push(model); }, _removeIndexEntry: function( model ) { … } }); var hydrantCollection = new (MapKit.Collection.extend({…}));
  5. hydrantCollection fetchTiles() TILE IDs prefetch() NEW TILE IDs request() tileIndex

    SERVER FETCHCONTROLLER fetchReady() displayModels() willFetch()
  6. var MapKit.Collection = Backbone.Collection.extend({ fetchTiles: function( tileIds, fetchController ) {

    fetchController.willFetch(); var tilesToRequest = this.prefetch(tileIds, fetchController); if( !tilesToRequest.length ) { fetchController.fetchReady(); } else { this.request(tilesToRequest, { success: function( data ) { var models = this.add(data); fetchController.displayModels(models); fetchController.fetchReady(); }, error: function() { fetchController.fetchReady(); } }); } } });
  7. var MapKit.Collection = Backbone.Collection.extend({ fetchTiles: function( tileIds, fetchController ) {

    fetchController.willFetch(); var tilesToRequest = this.prefetch(tileIds, fetchController); if( !tilesToRequest.length ) { fetchController.fetchReady(); } else { this.request(tilesToRequest, { success: function( data ) { var models = this.add(data); fetchController.displayModels(models); fetchController.fetchReady(); }, error: function() { fetchController.fetchReady(); } }); } } });
  8. prefetch: function( tileIds, fetchController ) { var tilesToRequest = [];

    tileIds.forEach(function( tileId ) { var models = this.tileIndex[tileId]; if( models ) { fetchController.displayModels(models); } else { tilesToRequest.push(tileId); } }, this); return tilesToRequest; }
  9. var MapKit.Collection = Backbone.Collection.extend({ fetchTiles: function( tileIds, fetchController ) {

    fetchController.willFetch(); var tilesToRequest = this.prefetch(tileIds, fetchController); if( !tilesToRequest.length ) { fetchController.fetchReady(); } else { this.request(tilesToRequest, { success: function( data ) { var models = this.add(data); fetchController.displayModels(models); fetchController.fetchReady(); }, error: function() { fetchController.fetchReady(); } }); } } });
  10. var MapKit.Collection = Backbone.Collection.extend({ initialize: function() { this.tileIndex = {};

    this.on('add', this._addIndexEntry, this); this.on('remove', this._removeIndexEntry, this); }, _addIndexEntry: function( model, collection, options ) { var tileId = model.get(‘tile_id'); this.tileIndex[tileId].models.push(model); }, _removeIndexEntry: function( model ) { … } }); var hydrantCollection = new (MapKit.Collection.extend({…}));
  11. defaults: { id: district_id: point: tier0: tier1: status: address: city:

    zipcode: year: kaliber: frequency: last_maintenance: } undefined, undefined, undefined, undefined, undefined, ‘ok’, undefined, undefined, undefined, 1970, undefined, 0, 0
  12. defaults: { id: district_id: point: tier0: tier1: status: address: city:

    zipcode: year: kaliber: frequency: last_maintenance: } 2345, 36, [5.3847, 43.7263], 18273849029, 1009283, ‘dry’, sparse: ‘Backstreet 3’, ‘Bone City’, ‘76354’, 2014, 200, 365, 1416865015, false
  13. fetchModel: function( id, options ) { var model = this.get(id)

    || this.add({id: id}, options); if( model.cid in this._pendingIds ) return model; this._pendingIds[model.cid] = true; this._pending.push(model); window.clearTimeout(this._groupTimer); this._groupTimer = _.delay(function fetch( self ) { var models = self._pending.splice(0, self._pending.length); var qs = “id=1,2,3,4”; self.fetch({ data: qs, success: function() { self._pendingIds = {}; } }); }, 50, this); return model; }
  14. Queue add() create() store() get() each() remove() MEMORY LOCALSTORAGE run()

    store() run() each() execute() get() busy() success() error() remove() DELAYED