Guest User

Untitled

a guest
Jan 11th, 2016
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import {isObject, isEmpty, size} from '../vendor/underscore'
  2.  
  3. // All instances of the Memory class
  4. const memories = {}
  5.  
  6. /**
  7.  * Listen for storage events and update the stored value for exising memory
  8.  * instances, if the key changes. These only fire, if the write happens in
  9.  * another tab of the same origin.
  10.  */
  11. window.addEventListener('storage', ({key, newValue}) => {
  12.     if (key in memories) {
  13.         memories[key].cached = parseSet(newValue)
  14.     }
  15. })
  16.  
  17. /**
  18.  * Parse a stringified set
  19.  * @param {string} set
  20.  * @returns {Object}
  21.  */
  22. function parseSet(set) {
  23.     let val
  24.     try {
  25.         val = JSON.parse(set)
  26.     }
  27.     catch(e) {}
  28.     return isObject(val) ? val : {}
  29. }
  30.  
  31. /**
  32.  * Self-expiring localStorage set manager
  33.  */
  34. export default class Memory {
  35.     /**
  36.      * Construct a new localStorage controller
  37.      * @param {string} key - localStorage key
  38.      * @param {int} expiry - Entry lifetime in days
  39.      */
  40.     constructor(key, expiry) {
  41.         this.key = key
  42.         memories[key] = this
  43.         this.expiry = expiry
  44.  
  45.         // Read the initial value
  46.         this.cached = this.read()
  47.  
  48.         // Purge old entries on start
  49.         setTimeout(() => this.purgeExpired(), 5000)
  50.     }
  51.  
  52.     /**
  53.      * Return current time in seconds
  54.      * @returns {int}
  55.      */
  56.     now() {
  57.         return Math.floor(Date.now() / 1000)
  58.     }
  59.  
  60.     /**
  61.      * Clear the stored set
  62.      */
  63.     purgeAll() {
  64.         localStorage.removeItem(this.key)
  65.     }
  66.  
  67.     /**
  68.      * Read and parse the stringified set from localStorage
  69.      * @returns {Object}
  70.      */
  71.     read() {
  72.         const key = localStorage.getItem(this.key)
  73.         if (!key) {
  74.             return {}
  75.         }
  76.         return parseSet(key)
  77.     }
  78.  
  79.     /**
  80.      * Return, if the given jey exists in the set
  81.      * @param {string} key
  82.      * @returns {bool}
  83.      */
  84.     has(key) {
  85.         return !!this.cached[key]
  86.     }
  87.  
  88.     /**
  89.      * Replace the existing set, if any, with the suplied one
  90.      * @param {Object} object
  91.      */
  92.     writeAll(set) {
  93.         if (isEmpty(set)) {
  94.             return this.purgeAll()
  95.         }
  96.         localStorage.setItem(this.key, JSON.stringify(set))
  97.     }
  98.  
  99.     /**
  100.      * Write a single key to the stored set
  101.      * @returns {int} - Size of new set
  102.      */
  103.     write(key) {
  104.         // When performing writes, best fetch everything, rather than rely on
  105.         // events for browser tab cache synchronisation. Browser backround tab
  106.         // optimisation might fuck us over.
  107.         this.cached = this.read()
  108.         this.cached[key] = this.now()
  109.         this.writeAll(this.cached)
  110.         return size(this.cached) // Return number of items
  111.     }
  112.  
  113.     /**
  114.      * Return the current size of the stored Set
  115.      */
  116.     size() {
  117.         return size(this.cached)
  118.     }
  119.  
  120.     /**
  121.      * Delete expired entries from set and write to localStorage
  122.      */
  123.     purgeExpired() {
  124.         this.cached = this.read()
  125.         const now = this.now(),
  126.             limit = 86400 * this.expiry,
  127.             expired = []
  128.         for (let key in this.cached) {
  129.             if (now > this.cached[key] + limit) {
  130.                 expired.push(key)
  131.             }
  132.         }
  133.         if (!expired.length) {
  134.             return
  135.         }
  136.         for (let key of expired) {
  137.             delete this.cached[key]
  138.         }
  139.         this.writeAll(this.cached)
  140.     }
  141. }
Advertisement
Add Comment
Please, Sign In to add comment