gr2m / localstorage-memory

localStorage-compatible API, but only stored in memory
23 stars 8 forks source link

Unable to create multiple instances #1

Open jasonkarns opened 9 years ago

jasonkarns commented 9 years ago

Would you be open to a PR that enabled multiple instances?

The API for localstorage and sessionstorage is identical. We're using this module in for our node test suite to mock out local and session storage. However, because this module acts as a singleton, we can't create separate stores (one to mock localStorage and another for sessionStorage).

Changing up the api of this so that it's possible to instantiate any number of stores would be greatly beneficial.

Something like:

var Storage = require('localstorage-memory');

var localStorage = new Storage();
var sessionStorage = new Storage();

localStorage.setItem('foo', 'bar');
sessionStorage.getItem('foo'); // -> undefined
gr2m commented 8 years ago

@jasonkarns man I'm so sorry, I didn’t watch this repo myself and only see your issue today. I'll think about it and get back to you :) Won’t forget this time

gr2m commented 8 years ago

Yeah I think that change would be great, as long as it will continue to work with humble-localStorage, but I don’t see a reason why it shouldn’t be possible to adjust this line here: https://github.com/gr2m/humble-localstorage/blob/master/lib/api.js#L18

leebenson commented 7 years ago

@gr2m - sorry to post nearly a year later, but any movement to this?

I'm doing server-side rendering of a Feathers.js + React chain, and need to create a new 'client' per request. Each client has its own localStorage (used alongside feathers' authentication handler) that is GC'd at the end of the request.

Being able to create multiple instances rather than share a global object would be awesome - thanks!

leebenson commented 7 years ago

I whipped up this quick class that wraps a Map. Since it's a class, you can instantiate it with new LocalStorage to create a new instance.

(You might need some babel transpiling to make the class properties work - check out my babel-preset-node5 for a version that works - links to Node 7.x at the bottom of the link):

Note: Untested. I'm due to try this out in production later today!

export default class LocalStorage {
  constructor() {
    this.cache = new Map();
  }

  get length() {
    return this.cache.size;
  }

  getItem = key => this.cache.get(key);

  setItem = (key, value) => {
    if (!value) {
      this.cache.delete(key);
      return;
    }
    this.cache.set(key, value);
  }

  removeItem = key => {
    this.cache.delete(key);
  }

  clear = () => {
    this.cache.clear();
  }
}
gr2m commented 7 years ago

I see your use case with the server-side rendering 👍

I think the right way to do this is to split up the source code into two files. require('localstorage-memory') will return the same singleton pre-initialised API. But then we could add require('localstorage-memory/create') which returns a factory for the API, where each instance has a separate memory store.

Don’t do classes, it’s not worth it, the case is to simple and classes are harder to test. We can release a new breaking release so folks can continue to use the current version which seems to be very stable. In the new release, we can get rid of bower support and add a built version to the npm package, it could work similarly to the setup of initilials, the browser-version is built before the release in the presemenatic-release task.

No need for babel and friends, this thing is way to simple for that :) Good old es5 & commonjs :v:

leebenson commented 7 years ago

Yeah, for universal usage, sticking with es5/no classes is probably easier. I need this exclusively for Node, where classes are supported natively and I've already got a pretty involved babel/webpack config, so it's no biggie.

Thinking about it some more, In my case, it might actually be better to use a Proxy instance alongside a class. That way the array accessors could work too.

gr2m commented 7 years ago

sounds like you should just go and do something custom for your app, it’s fairly simple anyway :)

leebenson commented 7 years ago

I think so too. I'll release a Node version to NPM later today using the Map/class/Proxy combo, for anyone that wants to use it exclusively SS. Thanks!

Offirmo commented 5 years ago

Yeah I think that change would be great, as long as it will continue to work with humble-localStorage, but I don’t see a reason why it shouldn’t be possible to adjust this line here: https://github.com/gr2m/humble-localstorage/blob/master/lib/api.js#L18

Since this change would be a major, it wouldn't affect humble-localStorage until they upgrade

gr2m commented 5 years ago

Since this change would be a major, it wouldn't affect humble-localStorage until they upgrade

It’s been a while since I looked into it, but I think humble-localStorage requires the singleton implementation it has today to simulate what browsers have, they have one global API. If humble-localStorage gets instantiated multiple times it needs to have the same localstorage-memory instance.

We could also make it a non-breaking change fairly easy by doing something like this:

var Storage = require('localstorage-memory/constructor');

We could do that now and think about a breaking change later?