Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Web Storage with cache expiration
// Generic abstraction of web storage operations available for local and session storage
function Storage(storage) {
this.moment = require('moment');
this.store = storage;
}
Storage.prototype = {
cache: function(key, value, ttl) {
if(!value || !this.store) {
return;
}
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API
// From Firefox 45 onwards, when the browser crashes/restarts, the amount of data saved per origin is limited to 10MB.
// This has been done to avoid memory issues caused by excessive usage of web storage.
// It means we have to check every time we want to cache data whether storage is available or not
if(this._isStorageAvailable()) {
this.store.setItem(key, JSON.stringify(value));
if (ttl) {
// Set expiration key as localstorage persists across sessions
// setTimeout to remove key wont work if window is closed
this.store.setItem(`${key}.ttl`, this.moment().add(ttl, 'ms'));
}
}
},
setCacheExpiry: function(key, ttl) {
if(!key.endsWith('.ttl')) {
// Use moment adding milliseconds to current time to set expiry
this.store.setItem(`${key}.ttl`, this.moment().add(ttl, 'ms'));
}
},
get: function(key) {
if(this.store) {
// Clear local storage item if expired
const found = this.store.getItem(`${key}.ttl`);
if (found && this.moment().isAfter(found)) {
this.remove(key);
this.remove(`${key}.ttl`);
return undefined;
}
// Return unexpired data
const data = this.store.getItem(key);
if(data) {
return JSON.parse(data);
}
}
return null;
},
remove: function(key) {
if(this.store) {
this.store.removeItem(key);
this.store.removeItem(`${key}.ttl`);
}
},
isAvailable: function() {
return this._isStorageAvailable();
},
_isStorageAvailable: function() {
try {
const x = '__storage_test__';
this.store.setItem(x, x);
this.store.removeItem(x);
return true;
} catch (e) {
return false;
}
},
clear: function() {
this.store.clear();
}
}
// Web storage abstraction
function WebStorage() {
this.localStorage = undefined;
this.sessionStorage = undefined;
this.setStorage();
}
WebStorage.prototype = {
setStorage: function() {
if(this._storageIsAvailable(window.localStorage)) {
this.localStorage = new Storage(window.localStorage);
}
if(this._storageIsAvailable(window.sessionStorage)) {
this.sessionStorage = new Storage(window.sessionStorage);
}
},
_storageIsAvailable: function(storage) {
if (!storage) {
return false;
}
try {
const x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
}
catch (e) {
return false;
}
},
};
module.exports = WebStorage;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment