Several ways to set the expiration time of localStorage

Several ways to set the expiration time of localStorage

When it comes to localStorage, friends who are familiar with the front-end must be familiar with it. We can use the getItem, setItem, removeItem, and clear APIs it provides to easily perform "read, write, and delete" operations on the data stored locally in the browser. However, compared to cookies, the only drawback of localStorage is that "the expiration time of each key cannot be set."

The localStorage property allows us to access a Document origin object Storage; the stored data will be saved in the browser session. localStorage is similar to sessionStorage, but the difference is that the data stored in localStorage can be retained for a long time; when the page session ends - that is, when the page is closed, the data stored in sessionStorage will be cleared.

We should also note that key-value pairs in localStorage are always stored as strings.

Problem Description

In actual application scenarios, we often need to make a certain "key" set in localStorage automatically invalid within a specified time, so based on this scenario, how do we solve it?

1. Basic solution

For those who are just familiar with the front end, they may give the answer immediately:

localStorage.setItem('dooring', '1.0.0')
// Set the validity period to one hour const expire = 1000 * 60 * 60;
setTimeout(() => {
  localStorage.setItem('dooring', '')
}, expire)

Of course, this solution can solve the problem temporarily, but if you want to set the validity period of any key, you need to write multiple timers using this solution, which has "extremely high maintenance costs and is not conducive to engineering reuse."

2. Intermediate solution

After front-end engineers have some work experience, they often consider the issues of engineering and reusability, and have a certain understanding of data structures, so they may have the following solutions:

  • Use **「localStorage** to store a mapping table of {key(key): expire(expiration time)}
  • Rewrite **"localStorage API"** and encapsulate the method twice

Similar code is as follows:

const store = {
  //Store expiration time map setExpireMap: (key, expire) => {
    const expireMap = localStorage.getItem('EXPIRE_MAP') || "{}"
    localStorage.setItem(
      'EXPIRE_MAP', 
      JSON.stringify({
      ...JSON.parse(expireMap),
      key: expire
    }))
  },
  setItem: (key, value, expire) => {
    store.setExpireMap(key, expire)
    localStorage.setItem(key, value)
  },
  getItem: (key) => {
    // Determine whether it is expired before getting the value const expireMap = JSON.parse(
      localStorage.getItem('EXPIRE_MAP') || "{}"
    )
    if(expireMap[key] && expireMap[key] < Date.now()) {
      return localStorage.getItem(key)
    }else {
      localStorage.removeItem(key)
      return null
    }
  }
  // ...
}

At first glance, this solution does solve the problem of reusability, and different teams can use this solution, but it still has some disadvantages:

  • When operating the store, two copies of data need to be maintained, and cache space is occupied
  • If EXPIRE_MAP is deleted by mistake, all expiration times will become invalid.
  • Lack of more flexible control over the operation process (such as operation status, operation callback, etc.)

3. Advanced solution

In order to reduce maintenance costs and space usage, and support certain flexible control and fault tolerance capabilities, what should we do?
Here I think of two similar solutions:

  1. Store the expiration time in the key, such as dooring|6000. Each time you take a value, use the separator "|" to take out the key and expire, and make a judgment
  2. Store the expiration time in value, such as 1.0.0|6000, and the rest is the same as 1

In order to have more encapsulation and reliability, we can also configure callbacks in different states, which can be simply implemented as follows:

const store = {
  preId: 'xi-',
  timeSign: '|-door-|',
  status: {
    SUCCESS: 0,
    FAILURE: 1,
    OVERFLOW: 2,
    TIMEOUT: 3,
  },
  storage: localStorage || window.localStorage,
  getKey: function (key: string) {
    return this.preId + key;
  },
  set: function (
    key: string,
    value: string | number,
    time?: Date & number,
    cb?: (status: number, key: string, value: string | number) => void,
  ) {
    let _status = this.status.SUCCESS,
      _key = this.getKey(key),
      _time;
    // Set the expiration time. If the time is not set, it defaults to one month. try {
      _time = time
        ? new Date(time).getTime() || time.getTime()
        : new Date().getTime() + 1000 * 60 * 60 * 24 * 31;
    } catch (e) {
      _time = new Date().getTime() + 1000 * 60 * 60 * 24 * 31;
    }
    try {
      this.storage.setItem(_key, _time + this.timeSign + value);
    } catch (e) {
      _status = this.status.OVERFLOW;
    }
    cb && cb.call(this, _status, _key, value);
  },
  get: function (
    key: string,
    cb?: (status: number, value: string | number | null) => void,
  ) {
    let status = this.status.SUCCESS,
      _key = this.getKey(key),
      value = null,
      timeSignLen = this.timeSign.length,
      that = this,
      index,
      time,
      result;
    try {
      value = that.storage.getItem(_key);
    } catch (e) {
      result = {
        status: that.status.FAILURE,
        value: null,
      };
      cb && cb.call(this, result.status, result.value);
      return result;
    }
    if (value) {
      index = value.indexOf(that.timeSign);
      time = +value.slice(0, index);
      if (time > new Date().getTime() || time == 0) {
        value = value.slice(index + timeSignLen);
      } else {
        (value = null), (status = that.status.TIMEOUT);
        that.remove(_key);
      }
    } else {
      status = that.status.FAILURE;
    }
    result = {
      status: status,
      value: value,
    };
    cb && cb.call(this, result.status, result.value);
    return result;
  },
  // ...
};

export default store;

In this way, we can achieve that each key has an independent expiration time, and can easily control the status of different operation results~

4. Hardcore Solution

Of course, the best solution is to use the xijs JavaScript library directly, because I have encapsulated the above complete implementation into the library. We only need to use the following solution to easily use the powerful "localStorage" method with expiration time:

// Install yarn add xijs first
import { store } from 'xijs';
// Set a key with an expiration time
store.set('name', 'dooring', Date.now() + 1000);
console.log(store.get('name'));
setTimeout(() => {
  console.log(store.get('name'));
}, 1000);

// Callback after setting success store.set('dooring', 'xuxiaoxi', Date.now() + 1000, (status, key, value) => {
  console.log('success');
});

At the same time, xijs is continuously expanding more useful tool functions to make business development more efficient. Currently, the following tool functions have been integrated:

  • 「store」 A cache library based on localStorage upper layer encapsulation that supports expiration time setting and supports operation callback
  • 「uuid」 Generates a unique id, supports setting the length
  • "randomStr" Generates a specified number of random strings
  • 「formatDate」 Out-of-the-box time formatting tool
  • "debounce" anti-shake function
  • "throttle" throttling function
  • 「url2obj」 Converts a url string to an object
  • "obj2url" converts an object into an encoded URL string
  • 「isPC」 Determine whether the device is a PC type

github address: https://github.com/MrXujiang/xijs

Document address:h5.dooring.cn/xijs

This concludes this article on several methods of setting localStorage expiration time. For more information about localStorage expiration time, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • About localStorage storage, reading, and deletion
  • How to operate localstorage in js
  • Use of Local Storage and Session Storage in JavaScript
  • A simple way to set validity and expiration time for localStorage
  • This article teaches you how to implement the expiration mechanism of localStorage
  • Count the usage and precautions of localStorage

<<:  Html/Css (the first must-read guide for beginners)

>>:  Detailed explanation of the 8 attribute values ​​of the background attribute (interview question)

Recommend

Native JS to achieve digital table special effects

This article shares a digital clock effect implem...

Detailed explanation and extension of ref and reactive in Vue3

Table of contents 1. Ref and reactive 1. reactive...

Solve the group by query problem after upgrading Mysql to 5.7

Find the problem After upgrading MySQL to MySQL 5...

How to use Navicat to export and import mysql database

MySql is a data source we use frequently. It is v...

PHP-HTMLhtml important knowledge points notes (must read)

1. Use frameset, frame and iframe to realize mult...

HTML code that can make IE freeze

We simply need to open any text editor, copy the f...

MySQL isolation level detailed explanation and examples

Table of contents 4 isolation levels of MySQL Cre...

How to check and organize website files using Dreamweaver8

What is the purpose of creating your own website u...

A brief discussion of 3 new features worth noting in TypeScript 3.7

Table of contents Preface Optional Chaining Nulli...

Realizing provincial and municipal linkage effects based on JavaScript

This article shares the specific code of JavaScri...

How does Zabbix monitor and obtain network device data through ssh?

Scenario simulation: The operation and maintenanc...

Two ways to write stored procedures in Mysql with and without return values

Process 1: with return value: drop procedure if e...

Solution to the problem of repeated triggering of functions in Vue project watch

Table of contents Problem description: Solution 1...

Implementation of Nginx configuration https

Table of contents 1: Prepare https certificate 2:...