24 comments

[ 2.6 ms ] story [ 60.0 ms ] thread
This is great, I love web interfaces that are completely async where you can do whatever you want in realtime and it "magically" gets stored on the server for me later.

This just makes loading up a page even faster as the data is more than likely already on your computer.

Will this work for offline? If someone views a todolist, makes some changes offline, then visits it later online will it sync the changes automatically?

Not entirely automatically. The app would have to explicitly sync the model when it believes it can.

I do plan to add a helper for that, that keeps a list of unsynced models. Then a function could be called when the server is reachable, or just periodically.

I look forward to seeing it. I definitely plan on using this in the future when that functionality is added.
I worked on a cross domain CouchDB connector(using the postmessage and eventsource APIs) for Backbone that would work pretty well with this.
This helper + the PhoneGap network event monitoring would make this indispensable for a bunch of projects. I know I would love it. Anyway I can 'tip' your work?
I've done this on company time so far, since we're using it for a product and atm I wouldn't have enough free time to work on it otherwise.

We're going to release soon, so in the next few weeks I'm likely to add dirty model syncing.

This sounds cool. Does the local storage extend to collections? Can I query for locally stored objects? (i.e. created or updated within a given date range)
It does work with collections, and it tries to reuse the cache if you first get a model independently and then through its collection.

There's no specific local querying beyond listing window.localStorage.

Fun stuff. What's the strategy for shared models?

If I make changes based on a model that I've read from my local cache ... while someone else edits the same model on the server ... how does that reconcile when I try later on to make a change?

No strategy at all. For what we're using it conflicts are impossible, so the last write always wins.
I've started using ShareJS[1] in a new app recently to handle real-time collaboration where conflicts are likely. It's spearheaded by an ex-Google Wave engineer and uses Operational Transformation principles to handle automatic merges.

I've been thinking for a little bit now that it would awesome to build a Backbone sync system that could cache things locally when the user is offline, then seamlessly handle bringing them back in sync with ShareJS.

[1] https://github.com/josephg/ShareJS

This is intriguing. I've spent a bit of time building Backbone projects that sync with the server (eg. https://github.com/napoleond/localModel) but until now have always resolved conflicts by choosing the model with the most recent time modified. (I have also played a bit with using WebSockets to keep the models up to date for every concurrent user, although that was mostly just for fun.) It would be way better to actually merge diffs in an intelligent manner, though. Thanks for the link!
Oh, wow! This is awesome; I'm just now at the point in a Backbone project where I was preparing to implement something similar, and wasn't exactly relishing the thought. It's awesome that I now have something to work with instead of having to roll my own.

I do have one suggestion, though: while it's of course not much work to compile the script to JavaScript, it couldn't hurt to include a current JS version in the repo for people who don't have Node & CoffeeScript installed.

Good point, added.
Thank you, I was about to ask for the same!
I wrote something very similar a week ago: https://github.com/scosman/Backbone.CachedModel

Differences:

- it works with any .sync implementation you might already have (JSON, XML, whatever). It just drops in, caching the server responses locally, not assuming anything about how the service works

- instead of overridding Backbone.Sync I let you extend CachedModel on a per model basis (that way some models can be cached locally while others are not)

I didn't include any fancy cache expiry, just using a simple localstorage.clear on login for now.

example usage: var User = Backbone.CachedModel.extend({ cacheName: 'USERS', });

Interesting. I may steal some code :)

I handle not sending models to the server with remote/local boolean attributes on the model. Certainly not as well decoupled as yours.

another thing to consider, Store.records is keeping everything in memory. Using only localstorage should save some memory (although it depends on the browser implementation)
Good point. On the other hand, localStorage access appears to block, sometimes quite a bit. I'll investigate some more.

It's a bit I inherited from Backbone.localStorage, and haven't looked into much.

Just what we needed! We were just planning on adding similar functionality into our Backbone app. I check Hacker News an hour later, and there it is!

Looking forward to seeing the offline sync helper you mentioned in another thread.

Very cool. I wrote something similar a while back: https://github.com/napoleond/localModel

My implementation leaves a lot to be desired with regards to re-use (there are certain project requirements which happened to be met by the project I built it for) but it does nicely manage automatic replication of the most recent version of models between server and client.

As far as I can tell, this implementation reads from the local model if it exists, otherwise it loads from the server? And writes always go to the server unless explicitly told otherwise?

Writes always go both locally and to the server unless told otherwise, yes.
It will only sync it when connectivity is restored if explicitly done so, yes.

Atm our users trigger syncs manually, but we're planning to move to PhoneGap network events as triggers for syncs.

Another one here, have been procrastinating adding this capability for a week now.

Now I just need to find (or write) some php code that will save/serve the fetched json model.