Hacker News new | past | comments | ask | show | jobs | submit login
An Identity Map for Backbone.js (shinetech.com)
43 points by marcfasel on Dec 26, 2012 | hide | past | favorite | 7 comments

Neat little implementation. A couple quick thoughts:

* Identity maps aren't a panacea -- If you're just getting started, and you don't yet know that you "want" an identity map, you don't necessarily need one. There are a bunch of situations where having the ability to model multiple versions of the same resource is useful. For example, an "editing" version of the resource with changes that may or may not be applied to the canonical version ... or a "conflict" version of the resource that has been changed on the server, that you can reconcile with the local version.

* Backbone Collections already maintain a map of id-to-model information for you, and you can rely on them as an identity map ... if you don't use "new". Instead, something like this:

    Backbone.Collection.prototype.lookup = function(id) {
      return this.get(id) || new this.model({id: id});

    // Then later, instead of `new` or `get`:

... would provide a simple implementation of the same behavior, without having to change the semantics of "new", or maintain an external id-to-object mapping that makes it harder for garbage collection to work later.

There's also a version of the above function that you can add that does "lookup or fetch from the server" -- another alternative is "lookup locally, fetch from the server, or create on the server". Whatever you need for your app.

I've implemented something similar in the same manner (over-riding `new`). The original idea came from here: http://backstage.soundcloud.com/2012/06/building-the-next-so...

One implementation detail I ran into is how to detect dupes. When you have Backbone Models, this is easy: every model has an `id`. But say you want to apply this same singleton behavior to a Backbone Collection, which don't have natively have `id`s. I saw two options:

1. Assign an `id` to the collection when instantiated (could just be a string, so that you can force a singleton only when you desire it).

2. De-dupe based on `instanceof` checks. The downside here is you always get a singleton even if you might want a one-off instance of a collection.

Are there any other options? Can your Identiy Map handle collections?

This is clever!

My solution has always been something to the tune of:

    var kyle = Person.getByName("kyle");
But your solution is better in that the interface need not change (there could be a lot of code to rewrite in my case, if the "new" keyword were already being used everywhere).

I do like it that in your solution the interface is (or remains) elegant, but I can't help but think, as a pythonista at heart, "explicit is better than implicit". So I'm little freaked out by the idea that code reading:

    var kyle = new Person("kyle");
isn't actually constructing a new instance.

Then again, the equivalent Python code does not at all guarantee it'll return a new object, and it's a very good use case for returning objects from JS constructors.

Interesting. I threw my take on a Backbone identity map up on Github. 31 extra lines of code. Just add a keepInSync: true attribute to models that should use the identity map.

It's a modified version of this code: http://news.ycombinator.com/item?id=3276990


Backbone-relational model solves this problem with a few additional features (and last version it's compatible with Backbone 0.9.9): https://github.com/PaulUithol/Backbone-relational

Nice approach, though it would seem to not be needed with Backbone 0.9.9, with the new 'update: true' option for fetching collections. (If you have a central data model for your application that is.)

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact