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

The difference between this.$router and this.$route in Vue and the push() method

The official document states: By injecting the ro...

Solve the problem of docker pull being reset

This article introduces how to solve the problem ...

Solve the error during connect exception in Docker

When you first start using Docker, you will inevi...

JavaScript to achieve floor effect

This article shares the specific code of JavaScri...

How to download excel stream files and set download file name in vue

Table of contents Overview 1. Download via URL 2....

Example code for implementing equal width layout in multiple ways using CSS

The equal-width layout described in this article ...

A brief analysis of adding listener events when value changes in html input

The effect to be achieved In many cases, we will ...

JavaScript microtasks and macrotasks explained

Preface: js is a single-threaded language, so it ...

mySql SQL query operation on statistical quantity

I won't say much nonsense, let's just loo...

How to redirect to other pages in html page within two seconds

Copy code The code is as follows: <!DOCTYPE ht...

How to upload the jar package to nexus via the web page

When using Maven to manage projects, how to uploa...

Summarize several common ranking problems in MySQL

Preface: In some application scenarios, we often ...

Share 5 JS high-order functions

Table of contents 1. Introduction 2. Recursion 3....

In-depth understanding of MySQL master-slave replication thread state transition

Preface The basic principle of MySQL master-slave...