In front-end development applications, performance has always been a point of attention, but the most intuitive way to judge the performance of an application is to look at the speed of page opening. One way to speed up page response is to use caching. A good caching strategy can shorten the distance between page request resources, reduce latency, and reduce bandwidth and network load because cached files can be reused.
Common front-end caching technologies are not described here, but are enhanced based on Storage using the same API as Map.
If you don’t understand ECMAScript 6, please read it first
Here is the basic code, which will be enhanced
class MinCache {// Stores the data in the name specified in the local Cacheset(name, data) { try { uni.setStorageSync(name, Data)} catch (e) {console.log(e)}} get (name) {let data
try {
data = uni.getStorageSync(name)
} catch (e) {
console.log(e)
}
returnData} // Remove the specified key delete (name) {try {uni.removeStoragesync (name)} catch (e) {console.log(e)}} // return a Boolean value, Has (name) {const value try {const res = uni.getStorageInfosync () value = res.keys.includes(name)} catch (e) { console.log(e) }returnValue} // Clear the local data cacheclear () {
try {
uni.clearStorageSync()
} catch (e) {
console.log(e)
}
}
}
export default MinCacheCopy the code
We know that caching is often harmful, so it’s best to set a time limit for removing data.
Class cacheecell {constructor (data, timeout) {this.data = data This.timeout = timeout // The time when the object was created this.createTime = date.now ()}}Copy the code
set (name, data, timeout = 1200) {
const cachecell = new CacheCell(data, timeout)
try {
uni.setStorageSync(name, cachecell)
} catch (e) {
console.log(e)
}
}
get (name) {
let data = null
try {
data = uni.getStorageSync(name)
if(! data)return null
const currentTime = Date.now()
const overTime = (currentTime - data.createTime) / 1000
if(overTime > data.timeout) { try { uni.removeStorageSync(name) data = null } catch (e) { console.log(e) } } } catch (e) { console.log(e) }return data
}Copy the code
The expiration time cache can be used in most business scenarios.
Uni-app Storage is implemented differently at different ends:
-
The H5 terminal is localStorage. The browser limits the size to 5M. It is a cache concept and may be cleared
-
The App side is the original Plus. storage with no size limitation, not cache and persistence
-
Each small program has its own storage API. The data storage life cycle is consistent with the small program itself, that is, data is always available unless the user actively deletes it or the data is automatically cleaned after a certain period of time.
-
The maximum length of data stored by a single key in wechat applet is 1MB, and the maximum length of all data stored is 10MB.
-
After converting a single piece of data into a string, the maximum length of the string is 200*1024. For the same Alipay user, the total upper limit of the same small program cache is 10MB.
-
Baidu, toutiao small program documents do not specify size limits
H5 supports WebSQL, indexedDB, and sessionStorage. App side also supports SQLite, IO file and other local storage solutions.
We can see that Storage in some end of the size limit, in fact, we just want to cache the data, not necessarily persistent.
This means that it is ok to use Storage within the application life cycle, and it is not good to operate Storage directly.
We know that ES6 has maps for caching
The following code is wrapped based on Map
let cacheMap = new Map()
let instance = null
let timeoutDefault = 1200
function isTimeout (name) {
const data = cacheMap.get(name)
if(! data)return true
if (data.timeout === 0) return false
const currentTime = Date.now()
const overTime = (currentTime - data.createTime) / 1000
if (overTime > data.timeout) {
cacheMap.delete(name)
return true
}
return false
}
class CacheCell {
constructor (data, timeout) {
this.data = data
this.timeout = timeout
this.createTime = Date.now()
}
}
class Cache {
set (name, data, timeout = timeoutDefault) {
const cachecell = new CacheCell(data, timeout)
return cacheMap.set(name, cachecell)
}
get (name) {
return isTimeout(name) ? null : cacheMap.get(name).data
}
delete (name) {
return cacheMap.delete(name)
}
has (name) {
return! isTimeout(name) }clear () {
return cacheMap.clear()
}
setTimeoutDefault (num) {
if (timeoutDefault === 1200) {
return timeoutDefault = num
}
throw Error('The cache can only set the default expiration time once')
}
}
class ProxyCache {
constructor () {
return instance || (instance = new Cache())
}
}
export default ProxyCacheCopy the code
Integrate Storage and Map encapsulated caches
So let’s analyze it
-
Storage and Map share the same API
-
Resolve the following underlined _ name on the cache to Storage, and Map also has a copy
-
-
Try not to operate Storage(slow read speed)
-
Storage must be loaded into Map when the application is initialized
-
-
Use it like a Vue plug-in
let cacheMap = new Map()
let timeoutDefault = 1200
function isTimeout (name) {
const data = cacheMap.get(name)
if(! data)return true
if (data.timeout === 0) return false
const currentTime = Date.now()
const overTime = (currentTime - data.createTime) / 1000
if (overTime > data.timeout) {
cacheMap.delete(name)
if (name.startsWith('_')) {
try {
uni.removeStorageSync(name)
} catch (e) {
console.log(e)
}
}
return true
}
return false
}
class CacheCell {
constructor (data, timeout) {
this.data = data
this.timeout = timeout
this.createTime = Date.now()
}
}
class MinCache {
constructor (timeout) {
try {
const res = uni.getStorageInfoSync()
res.keys.forEach(name => {
try {
const value = uni.getStorageSync(name)
cacheMap.set(name, value)
} catch (e) {
console.log(e)
}
})
} catch (e) {
console.log(e)
}
timeoutDefault = timeout
}
set (name, data, timeout = timeoutDefault) {
const cachecell = new CacheCell(data, timeout)
let cache = null
if (name.startsWith('_')) {
try {
uni.setStorageSync(name, cachecell)
cache = cacheMap.set(name, cachecell)
} catch (e) {
console.log(e)
}
} else {
cache = cacheMap.set(name, cachecell)
}
return cache
}
get (name) {
return isTimeout(name) ? null : cacheMap.get(name).data
}
delete (name) {
let value = false
if (name.startsWith('_')) {
try {
uni.removeStorageSync(name)
value = cacheMap.delete(name)
} catch (e) {
console.log(e)
}
} else {
value = cacheMap.delete(name)
}
return value
}
has (name) {
return! isTimeout(name) }clear () {
let value = false
try {
uni.clearStorageSync()
cacheMap.clear()
value = true
} catch (e) {
console.log(e)
}
return value
}
}
MinCache.install = function (Vue, {timeout = 1200} = {}) {
Vue.prototype.$cache = new MinCache(timeout)
}
export default MinCacheCopy the code
Method of use
Name The name starting with underscore _ is cached to the Storage, and Map also has a copy
The event name | parameter | instructions | The return value |
---|---|---|---|
set | Name Cache key,data Cache data,timeout(unit: s) Cache duration. The default cache duration is 1200s. If timeout is set to 0, the cache is permanent | Setting cached data | Map collections |
get | Name Cache key | Get data (null will be returned if cache expires) | Returns the cached data data |
has | Name Cache key | Check the value | true/false |
delete | Name Cache key | Delete the data | true/false |
clear | – | Clear Storage and Map cache data | true/false |
Vue. Use (MinCache) // Set the default Cache time // vue.use (M)inCache, {timeout: 600})Copy the code
// 'name'Representations that do not begin with an underscore will be cached in the Map, and this will be valid for as long as the program lives.$cache.set('name'.'MinCache') // If the expiration time is set to 0, it will not expire.'test'It is not named with an underscore to indicate that this is permanently cached during the program life cycle.$cache.set('test'.'testdemo', 0) // If the expiration time is set to 0, it will not expire.'_imgURL'The name is underlined to indicate permanent cache to Storage this.$cache.set('_imgURL'.'data', 0)Copy the code
ImgURL = this. ImgURL = this.$cache.get('_imgURL')
this.name = this.$cache.get('name')
this.test = this.$cache.get('test')Copy the code
For details, see Github