Caching is one of the effective ways to improve web applications, especially when users are limited by network speed. Improve system responsiveness and reduce network consumption. Of course, the closer the content is to the user, the faster the cache will be and the more effective the cache will be.
I have personally written a front-end API request caching solution before . The in-memory cache and expiration logic are introduced. Later, I also wrote a front-end storage tool library , which used adapters to handle different storage media (memory, IndexedDB, localStorage, etc.).
However, caching still needs to be optimized in some specific scenarios. For example, users need to obtain necessary data through certain interfaces when logging in or filling out forms, and these interfaces are provided by third-party platforms. These interfaces may experience errors or timeouts. If the current data is very real-time, the developer must retry or contact the third-party platform to handle the corresponding error. If the real-time nature of the data is not strong, local caching can currently be used.
Generally speaking, when obtaining time-sensitive cache, we will check and delete the current data. The code abbreviation is as follows:
// The corresponding modules and functions of the cache const EXTRA_INFO_CACHE_KEY = 'xxx.xxx.xxx' ; // The cache duration is 7 days const CACHE_TIME = 7 * 24 * 60 * 60 * 1000 ; const getCachedExtraInfo = () => { const cacheStr = localStorage . getItem ( ` ${EXTRA_INFO_CACHE_KEY} . ${userId} ` ); if (!cacheStr) { return null ; } let cache = null ; try { cache = JSON . parse (cacheStr); } catch () { return null ; } if (!cache) { return null ; } // The cache has expired, return null directly if ((cache. expiredTime ?? 0 ) < new Date (). getTime ()) { return null ; } return cache.data ; } const getExtraInfo = () => { const cacheData = getCachedExtraInfo (); if (cacheData) { return Promise . resolve (cacheData); } return getExtraInfoApi (). then ( res => { localStorage . setItem ( ` ${EXTRA_INFO_CACHE_KEY} . ${userId} ` , { data : res, expiredTime : ( new Data ()). getTime () + CACHE_TIME , }); return res; }); }
If there is an access error problem in the interface at this time, many users whose data has expired will not be able to use the function normally. Adding a retry function at this time may solve some errors. At this time, we will not consider the logic of retrying.
Considering that the vast majority of users’ corresponding data will not be modified, the corresponding code does not need to delete the data. Instead, a timeout flag is returned.
const EXTRA_INFO_CACHE_KEY = 'xxx.xxx.xxx' ; const CACHE_TIME = 7 * 24 * 60 * 60 * 1000 ; const getCachedExtraInfo = () => { const cacheStr = localStorage . getItem ( ` ${EXTRA_INFO_CACHE_KEY} . ${userId} ` ); if (!cacheStr) { return null ; } let cache = null ; try { cache = JSON . parse (cacheStr) } catch () { return null ; } if (!cache) { return null ; } if ((cache. expiredTime ?? 0 ) < new Date (). getTime ()) { return { data : cache. data , // The data has timed out isOverTime : true , }; } return { data : cache. data , // The data does not have a timeout isOverTime : false , }; } const getExtraInfo = () => { const cacheInfo = getCachedExtraInfo (); // The corresponding data will be returned only if the data has not timed out if (cacheInfo && !cacheInfo. isOverTime ) { return Promise . resolve (cacheInfo. data ); } return getExtraInfoApi (). then ( res => { localStorage . setItem ( ` ${EXTRA_INFO_CACHE_KEY} . ${userId} ` , { data : res, expiredTime : ( new Data ()). getTime () + CACHE_TIME , }); return res; }). catch ( err => { // Only return if there is data, otherwise continue to throw an error if (cacheInfo) { return cacheInfo. data ; } throw err; }) }
In this case, we can ensure that the vast majority of users can continue to use it normally. However, if the corresponding interface is unstable, users will have to wait for a long time before they can continue to use it.
At this time, developers can consider abandoning asynchronous code completely and reducing cache time.
const EXTRA_INFO_CACHE_KEY = 'xxx.xxx.xxx' ; // Reduce cache aging to 5 days const CACHE_TIME = 5 * 24 * 60 * 60 * 1000 ; const getCachedExtraInfo = () => { const cacheStr = localStorage . getItem ( ` ${EXTRA_INFO_CACHE_KEY} . ${userId} ` ); if (!cacheStr) { return null ; } let cache = null ; try { cache = JSON . parse (cacheStr) } catch () { return null ; } if (!cache) { return null ; } if ((cache. expiredTime ?? 0 ) < new Date (). getTime ()) { return { data : cache. data , isOverTime : true , }; } return { data : cache. data , isOverTime : false , }; } const getExtraInfo = () => { const cacheInfo = getCachedExtraInfo (); // If it times out, get it and use it next time if (cacheInfo. isOverTime ) { getExtraInfoApi (). then ( res => { localStorage . setItem ( ` $ {EXTRA_INFO_CACHE_KEY} . ${userId} ` , { data : res, expiredTime : ( new Data ()). getTime () + CACHE_TIME , }) }) } return cacheInfo.data }