Skip to content

Instantly share code, notes, and snippets.

@bmcminn
Last active January 6, 2020 23:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bmcminn/5750204a6775e6d854793f2160ecff12 to your computer and use it in GitHub Desktop.
Save bmcminn/5750204a6775e6d854793f2160ecff12 to your computer and use it in GitHub Desktop.
A set of Javascript helper functions that trivialize a lot of tedious things, like cacheing and cache busting :P
/**
* Storage API helper method that sets a key/value in specified storage API with
* an optional cache duration in minutes
* @private
* @sauce https://developer.mozilla.org/en-US/docs/Web/API/Storage/setItem
*
* @param {object} StorageAPI Storage API object to use for .getItem() calls
* @param {string} key A DOMString containing the name of the key you want to create/update
* @param {any} value The value you want to give the key you are creating/updating
* @param {integer} durationInMinutes The time in minutes the item should be valid for, used for passively expiring cache
* @return {any} The initial value data
*/
function _setItem(StorageAPI, key, value, durationInMinutes=-1) {
const MINUTES = 1000 * 60
// if durationInMinutes is greater than 0 minutes, calc the expiration time in microseconds
let expires = durationInMinutes > 0
? new Date().getTime() + (Math.abs(durationInMinutes) * MINUTES)
: null
// NOTE: this uses ES6 Object property shorthand, modify as necessary
// @sauce: https://alligator.io/js/object-property-shorthand-es6/
let data = JSON.stringify({
expires,
value,
})
StorageAPI.setItem(key, data)
return value
}
/**
* Storage API helper method to verify item cache before returning the desired data
* @private
* @sauce https://developer.mozilla.org/en-US/docs/Web/API/Storage/getItem
*
* @param {object} StorageAPI Storage API object to use for .getItem() calls
* @param {string} key A DOMString containing the name of the key you want to create/update
* @return {boolean} false If the storage item does not exist, or is expired, returns false
* @return {any} value If the storage item exists and is not expired, returns the stored data
*/
function _getItem(StorageAPI, key) {
let data = JSON.parse(StorageAPI.getItem(key))
// check if storage key value exists
if (!data) {
return false
}
// check if storage key is expired
if (data.expires && data.expires < new Date().getTime()) {
return false
}
return data.value
}
/**
* Alias of storage.removeItem method
* @private
* @sauce https://developer.mozilla.org/en-US/docs/Web/API/Storage/removeItem
*
* @param {object} StorageAPI The storage API object to be used (eg: localStorage, sessionStorage)
* @param {string} key A DOMString containing the name of the key you want to delete
* @return {boolean} Returns true or false if the item was successfully deleted
*/
function _deleteItem(StorageAPI, key) {
StorageAPI.removeItem(key)
return StorageAPI.getItem(key) ? true : false
}
/**
* Storage aliases of StorageAPI.setItem() with optional cache duration in minutes
* @param {string} key A DOMString containing the name of the key you want to create/update
* @param {any} value The value you want to give the key you are creating/updating
* @param {integer} durationInMinutes An Integer of time in minutes you wish this value to be valid for
* @return {any} The initial value data
*/
export function lsSetItem(key, value, durationInMinutes = 0) { return _setItem(localStorage, key, value, durationInMinutes) }
export function ssSetItem(key, value, durationInMinutes = 0) { return _setItem(sessionStorage, key, value, durationInMinutes) }
/**
* Storage aliases of StorageAPI.getItem()
* @param {string} key A DOMString containing the name of the key you want to recall
* @return {any} The initial value data
*/
export function lsGetItem(key) { return _getItem(localStorage, key) }
export function ssGetItem(key) { return _getItem(sessionStorage, key) }
/**
* Storage aliases of StorageAPI.removeItem()
* @param {string} key A DOMString containing the name of the key you want to delete
* @return {boolean} True if the deletion was successful
*/
export function lsDeleteItem(key) { return _deleteItem(localStorage, key) }
export function ssDeleteItem(key) { return _deleteItem(sessionStorage, key) }
// todos should be an array of objects
let todos = fetchTodos();
async function fetchTodos(refresh = false) {
const lsLabel = 'todos'
const ttl = 60 // time-to-live in minutes
let todos = lsGetItem(lsLabel)
// if cache doesn't exist OR user forces the refresh
if (!todos || refresh) {
const res = await fetch('/api/todos')
todos = await res.json()
todos = lsSetItem(lsLabel, todos.data.todos, ttl);
}
return todos
}
import axios from 'axios'
import { lsGetItem, lsSetItem } from './path/to/storage.helpers.js'
let store = new Vuex.Store({
state: {
isLoadingTodos: false,
todos: [],
},
mutations: {
SET_TODOS(state, todos) {
state.todos = todos
},
IS_LOADING_TODOS(state, update) {
state.isLoadingTodos = todos
},
},
actions: {
async fetchTodos({ commit }, options) {
const lsLabel = 'todos'
const opts = Object.assign({}, {
refresh: false
}, options)
// set loading state to true
commit('IS_LOADING_TODOS', true)
// query the todos API route
let todos = lsGetItem(lsLabel)
if (!todos || opts.refresh) {
let res = await axios.get('/api/todos')
todos = lsSetItem(lsLabel, res.data.todos, 60) // cache result for 60 minutes
}
commit('IS_LOADING_TODOS', false)
commit('SET_TODOS', todos)
},
},
getters: {
getTodos(state) {
return state.todos
},
getIncompletedTodos(state) {
return state.todos.filter(todo => !todo.done)
},
},
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment