The JavaScript blog.


libraries modules tabs localStorage client-side

The Local Storage Bridge

Posted on .

Doing something as simple as passing values between iframes and tabs is surprisingly awkward, and you'll end up trying anything to get it to work. Krasimir Tsonev has created a library called lsbridge (GitHub: krasimir/lsbridge, License: MIT, npm: lsbridge), or Local Storage Bridge. It allows you to send messages between tabs using Local Storage as a communication channel.


The API uses the .send and .subscribe methods to pass messages one way. You can also call lsbridge.isLSAvailable to check if the Local Storage API itself is available. Here's an example of the usage:

lsbridge.send('my-namespace', { message: 'Hello world!' });

lsbridge.subscribe('my-namespace', function(data) {  
  console.log(data); // prints: { message: 'Hello world!'}

console.log(lsbridge.isLSAvailable); // prints "true" or "false"  

Internally, lsbridge uses a setTimeout polling loop to set and remove items. The interval is 100 milliseconds, and there's a separate interval for item removal which is set to a second.

This is a pragmatic way to send data between tabs that doesn't require ugly hacks. For more context behind the library, see Krasimir's blog post Using Local Storage as a communication channel.


data localStorage rest cache


Posted on .

Asaf Katz sent in JSData (GitHub: js-data/js-data, License: MIT, npm: js-data, Bower: js-data) by Jason Dobry, a model layer for caching data. It supports adapters for sending data to persistence layers, so you can install DSHttpAdapter (npm/Bower: js-data-http) to send data to a REST server or DSLocalStorageAdapter (npm/Bower: js-data-localstorage) for browser-based storage. There are even adapters for RethinkDB, Firebase, and Redis.

One nice thing about JSData is it uses Object.observe to watch for changes to data, so it doesn't need any special getters or setters. It also supports promises, so you can use then after finding or inserting data.

It also has more advanced ORM-style features like relations, computed properties, lifecycle methods, and data validation. The schema and validation API isn't based on JSON-Schema, but it has the kinds of features you've probably seen in other ORMs and ODMs like Mongoose:

var store = new JSData.DS();

var User = store.defineResource({  
  name: 'user',
  schema: {
    id: {
      type: 'string'
    name: {
      type: 'string',
      maxLength: 255
    email: {
      type: 'string',
      nullable: false

  name: 'John'
}).catch(function(err) {
  // Email errors will be in err.email.errors

This is an example I adapted from the Schemata and Validation documentation.

JSData was originally written for AngularJS, but is now framework-agnostic. However, there is an Angular integration guide which shows how it can be used with Angular applications.

Because JSData can be used with Node and browsers, you could use it to define reusable models for single-page apps that sync when the server is available. It'll also work well if you're used to Rails-inspired frameworks like Ember, and you're used to working with fat models that include data validation and lifecycle methods.


redis browser localStorage ES6 proxies

ES6 Metaprogramming, Barn

Posted on .

ES6 Metaprogramming

The last time I seriously looked at JavaScript metaprogramming I tried all kinds of dubious things like exploiting the with statement. With ECMAScript 6 proxies, the situation might be about to change. In Meta programming with ECMAScript 6 proxies, Dr. Axel Rauschmayer writes about the concept of metaprogramming, the different approaches (introspection, self-modification, intercession), and provides JavaScript examples.

This article includes an overview of proxies and what they're useful for, and shows how they can be used for intercepting method calls. He also mentions how proxies impact performance:

Data binding is a complex topic. Given its popularity and concerns over proxies not being performant enough, a dedicated mechanism has been created for data binding: Object.observe(). It will probably be part of ECMAScript 7 and is already supported by Chrome.

This is an in-depth article that is worth taking some time over, but will influence many people who are creating the next generation of ECMAScript 6-based APIs.


Barn (GitHub: arokor/barn, License: MIT, npm: barn) by Aron Kornhall is an API for localStorage that is based on Redis. The idea is to make operations atomic, so they survive things like a tab being closed or unexpected exceptions.

If you're used to Redis, then you might like this:

var barn = new Barn(localStorage);

barn.set('key', 'val');  
console.log(barn.get('key')); // val

barn.lpush('list', 'val1');  
barn.lpush('list', 'val2');  
console.log(barn.rpop('list')); // val1  
console.log(barn.rpop('list')); // val2  

Internally a mutating flag is used to provide a locking mechanism around the localStorage access. I think this should prevent issues that you might get when performing multiple writes, because the Web Storage specification says writes don't wait until the data has been written to disk.

Barn itself is based on NSStorage, which is also written by Aron. NSStorage is a smaller module that provides namespacing for the Web Storage API.


localStorage ES6

Cross-Storage: Share Local Data Across Domains

Posted on .


The localStorage API has some limitations, which you may need to work around for larger applications. The new cross-storage (License: Apache 2.0, npm: cross-storage, Bower: cross-storage) library from Daniel St. Jules at Zendesk adds support for cross-domain localStorage with permissions. It even has an ES6 Promise API.

It uses two components: hubs and clients. Hubs can set permissions based on on domain, and this is enforced using the same-origin policy. The available types of access are read, write, and delete (get, set, del).

  { origin: /\.example.com$/, allow: ['get'] },
  { origin: /:(www\.)?example.com$/, allow: ['get', 'set', 'del'] }

Clients can then access the hub like this:

var storage = new CrossStorageClient('https://store.example.com/hub.html');

storage.onConnect().then(function() {  
  // Set a key with a TTL of 90 seconds
  return storage.set('newKey', 'foobar', 90000);
}).then(function() {
  return storage.get('existingKey', 'newKey');
}).then(function(res) {
  console.log(res.length); // 2
}).catch(function(err) {
  // Handle error

Notice that the onConnect method returns a promise which is fulfilled when a connection has been established with the hub. You could also call storage.close to end the connection, which is actually implemented with an iframe.

Daniel recommends using the es6-promise polyfill for older browsers.

The project uses Gulp to build the client-side code, and comes with tests that use zuul.


frameworks localStorage mv*

MV* and Local Storage

Posted on .

Most AngularJS and Backbone.js projects that I've worked on have persisted data to a remote API. What about those times when storing data in the browser is sufficient? Enterprising developers have added support for localStorage to some MVC frameworks, but before dropping one of these plugins or libraries into your project you need to know a little background about the API and its limitations.

Browser Support

If you're already set on building a modern, single page web application, legacy browser support probably isn't a huge deal. The Can I use Web Storage page shows most browsers we typically target are supported. It refers to "name/value pairs" because it's talking about the localStorage API.

The localStorage API

If you've never used it before, then you can think of window.localStorage as a key/value store for strings. You can stick any JavaScript value you like in there, but a string will be returned on retrieval.

window.localStorage.setItem('age', 18);  
// "18"

This means you should think carefully about what data you store. Aspirations of creating a browser-based Photoshop backed by localStorage isn't architecturally sensible -- it would be nice if binary data could be stored, but for now you'll have to make do with strings.

The storage limit in most browsers is 5 MB, which probably doesn't sound like much, but it's actually 1000 times more than is supported by cookies.


There are examples of apps that use localStorage on the AngularJS blog. One that I downloaded and picked apart was FoodMe by Igor Minar. In FoodMe, Igor creates a localStorage service which basically just wraps window.localStorage so it can be loaded with dependency injection. The $scope is then watched, and a string version of a given record is dumped into localStorage using JSON.stringify:

foodMeApp.factory('customer', function($rootScope, localStorage) {  
  var LOCAL_STORAGE_ID = 'fmCustomer';
  var customerString = localStorage[LOCAL_STORAGE_ID];

  var customer = customerString ? JSON.parse(customerString) : {
    name: undefined,
    address: undefined

  $rootScope.$watch(function() { return customer; }, function() {
    localStorage[LOCAL_STORAGE_ID] = JSON.stringify(customer);
  }, true);

  return customer;

The record is loaded from localStorage, and serialised using JSON.parse and JSON.stringify. Notice that Igor has used the object-style API: localStorage.setItem(key, value) and localStorage[key] = value are equivalent.


Jerome Gravel-Niquet created Backbone.localStorage (GitHub: jeromegn / Backbone.localStorage, License: MIT, bower: backbone.localStorage), which allows collections to store data with localStorage. It's a drop-in solution -- barely any configuration is required. All you need to do is add a localStorage property to your collection classes.

Backbone.localStorage has tests, and the author is still updating it. GitHub currently lists 31 contributors.


This isn't meant to be an exhaustive review of localStorage libraries, but I thought I'd also mention Knockout. knockout.localStorage (GitHub: jimrhoskins / knockout.localStorage) by Jim Hoskins makes ko.observable and ko.observableArray objects able to persist data to localStorage. You'll need to specify a persist property which includes the key to store the observable's data under.

It's not quite as well-maintained or tested as Backbone.localStorage, but it does the job. There are some open pull requests that add things like AMD support.


The Web Storage specification also defines a "storage" event. It fires when data changes, but you can't stop it unlike other DOM events. This might make a more convenient bridge to data-binding frameworks.


If you've made an amazing single page app that persists data to localStorage, and you're interested in adding a server-side API so users can save and sync data, what do you do? Well, step back and redefine the problem. Since localStorage is limited in size, why not use it like a caching layer? Your application could store data locally until a server is available, which suits a lot of use-cases, including mobile deployment. This is exactly what Backbone Caching Sync by Yiorgis Gozadinos does.


Another use people have found for localStorage is caching client-side assets. One example of this is basket.js by Addy Osmani.

Bing and Google Search make extensive use of localStorage for stashing SCRIPT blocks that are used on subsequent page views. None of the other top sites from my previous post use localStorage in this way. Are Bing and Google Search onto something? Yes, definitely.


If you need to persist data, localStorage can slot into data-binding and MVC/MVVC frameworks rather nicely. There are libraries out there, but with JSON.parse and JSON.stringify it's trivial to store data. For applications with a server, then localStorage can be used as a temporary cache, which has the added benefit of helping support devices with intermittent network access.