开门见山地说,这篇文章【又】是一篇安利软文~,安利的对象就是 tua-storage。html
顾名思义,这就是一款存储数据的工具。node
用 tua-storage 好处大大的有么?
那必须滴~,下面开始个人表演~react
平常开发中,在不一样的平台下因为有不一样的存储层接口,因此每每致使相同逻辑的同一份代码要写几份儿。ios
例如,小程序中保存数据要使用【异步】的 wx.setStorage
、wx.getStorage
或对应的同步方法;git
而在 web 端使用 localStorage 的话,则是【同步】的 setItem
、getItem
等方法;github
在 React-Native 的场景下,使用的又是 AsyncStorage
中【异步】的 setItem
、getItem
...web
然而,通过 tua-storage
的二次封装,以上两个方法统一变成了:axios
save
: 异步保存load
: 异步读取此外还有一些其余方法:小程序
clear
: 异步清除(删除多个)remove
: 异步删除(删除单个)getInfo
: 异步获取信息(如 keys
)详情参阅这里的文档react-native
在某些场景下正好须要调用同步方法的话,咋办咧?
与 Node.js 的 api 风格差很少,在上述异步方法后面加上 Sync
就是对应的同步方法:
saveSync
loadSync
clearSync
removeSync
getInfoSync
那么在 AsyncStorage
的场景下,压根就没有同步方法时调用以上方法会怎么样呢?
嗯,你猜得没错,会直接报错...
如何区分不一样的场景呢?
在初始化的时候传递 storageEngine
便可:
import TuaStorage from 'tua-storage' const tuaStorage = new TuaStorage({ // 小程序 storageEngine: wx, // web storageEngine: localStorage, // React-Native storageEngine: AsyncStorage, // Node.js storageEngine: {}, })
注意:传递的是【对象】,而非字符串!
对于一个二次封装多端存储层的库来讲,保证多端 api 的统一仅仅是常规操做而已。
tua-storage
的另外一大亮点就是数据同步功能。
想一想平时咱们是怎么使用存储层的
正好存储层里有这个数据
假如存储层里没这个数据
各位有没有看出其中麻烦的地方在哪儿?数据同步部分的复杂度全留给了业务侧。
让咱们回归这件事的【初心】:我仅仅须要获取这个数据!我无论它是来自存储层、来自接口数据、仍是来自其余什么地方...
所以 tua-storage
在读取数据时很贴心地提供了一个 syncFn
参数,做为数据同步的函数,当请求的数据不存在或已过时时自动调用该函数。而且数据同步后默认会保存下来,这样下次再请求时存储层中就有数据了。
syncParams
的使用场景是接口须要传参时,这些参数会传给 syncFn
。
tuaStorage.load({ key: 'some data', syncFn: ({ a }) => axios('some api url' + a), // 如下参数会传到 syncFn 中 syncParams: { a: 'a' }, })
这么一来,存储层就和接口层对接起来了。业务侧不再用手动调用 api 获取数据。
每次读取数据时若是都要手动传同步函数,实际编码时仍是很麻烦...
不急,吃口药~
tua-storage
在初始化时可以传递一个叫作 syncFnMap
参数。顾名思义,这是一个将 key
和 syncFn
映射起来的对象。
const tuaStorage = new TuaStorage({ // ... syncFnMap: { 'data one': () => axios('data one api'), 'data two': () => axios('data two api'), // ... }, }) // 不用手动传 syncFn,默认匹配 syncFnMap 中的对应函数 tuaStorage.load({ key: 'data one' })
其实手动编写每一个 api 请求函数也是很繁琐的,要是有个根据配置自动生成请求函数的库就行了~
诶~,巧了么不是~。各位开发者老爷们了解一下一样跨平台的 tua-api ~?
tua-storage
搭配 tua-api
以后会变成这样
import TuaStorage from 'tua-storage' import { getSyncFnMapByApis } from 'tua-api' // 本地写好的各类接口配置 import * as apis from '@/apis' const tuaStorage = new TuaStorage({ syncFnMap: getSyncFnMapByApis(apis), })
通常各个平台的存储层都没有数据过时这一逻辑。但在使用 tua-storage
时默认每一个数据都有过时时间这一属性。
默认为 30 秒,能够在初始化时配置默认超时时间。
import TuaStorage from 'tua-storage' const tuaStorage = new TuaStorage({ // 改成 60 秒 defaultExpires: 60, }) // 返回一个 Promise tuaStorage .save({ key: 'data key', data: { foo: 'bar' }, // 这里传递的过时时间优先级更高 expires: 90, }) .then(console.log) .catch(console.error) // 保存到 storage 中的数据大概长这样 // key 以前会加上初始化传入的默认前缀 { 'TUA_STORAGE_PREFIX: data key': { expires: 90, rawData: { foo: 'bar' }, }, }
为了保证存在 storage 中的数据名称不冲突,以及实现版本控制,tua-storage
默认有一个存储前缀:storageKeyPrefix
。
默认值为 TUA_STORAGE_PREFIX:
,因此在上一小节中保存的数据会有一个奇怪的前缀。
保证名称不冲突很好理解,如何实现版本控制呢?
clear
函数可以接受一个白名单数组(由于内部是经过 indexOf
来判断的,因此没必要填写完整的 key
值)。
import TuaStorage from 'tua-storage' const tuaStorage = new TuaStorage({ ... }) tuaStorage.clear(['key']) .then(console.log) .catch(console.error) // 假设如今 storage 中有如下数据 { 'foo': {}, 'bar': {}, 'foo-key': {}, 'bar-key': {}, } // 清除后剩下的数据是 { 'foo-key': {}, 'bar-key': {}, }
因此在调用 clear
时,在白名单中传入新的存储前缀,便可实现删除上一版本数据的功能。
import TuaStorage from 'tua-storage' // 上一版本的前缀 const prefix1 = 'STORAGE_PREFIX_V1.0: ' // 这一版本的前缀 const prefix2 = 'STORAGE_PREFIX_V1.1: ' const tuaStorage = new TuaStorage({ // 将默认前缀切换成新版本的 storageKeyPrefix: prefix2, }) // 开始清除上个版本的数据 tuaStorage.clear([ prefix2 ]) .then(console.log) .catch(console.error)
默认在启动时会进行一次过时数据清理(能够关闭),以后每过一段时间会再次清理。
什么样的数据会被清理呢?
首先固然是清理已到过时时间的数据,即有一个属性为 expires
的数据,且当前时间已超过了该时间。
一旦遇到不知足格式的数据(非对象、没有 expires
属性)则跳过,这样就不会误清除其余程序保存的数据。
在初始化时可传入 autoClearTime
修改默认自动清理时间间隔。
默认为一分钟,注意是以秒为单位。
在某些场景下,可能不方便写过时时间,这时默承认以传递 expires: null
,标记该数据永不过时。
不喜欢用
null
标记?
大丈夫~,初始化时传递 neverExpireMark
便可修改成你喜欢的别的标记。
import TuaStorage from 'tua-storage' const tuaStorage = new TuaStorage({ neverExpireMark: 'never', }) // 永不过时 tuaStorage.save({ key: 'some key', data: 'some data', expires: 'never', })
假设如今有一组数据须要保存或读取,常规操做就是使用 Promise.all
发起多个操做。
import TuaStorage from 'tua-storage' const tuaStorage = new TuaStorage({ ... }) const dataToBeSaved = [ { key: 'key one', data: 'some data' }, { key: 'key two', data: 'some data' }, ] // 异步 const result = dataToBeSaved .map(tuaStorage.save.bind(tuaStorage)) .then(Promise.all.bind(Promise)) // 同步 const result = dataToBeSaved .map(tuaStorage.saveSync.bind(tuaStorage))
讲道理这样写仍是挺烦的...因此 tua-storage
的各个 api 还支持直接传入数组:
// 异步 tuaStorage.save(dataToBeSaved) .then(console.log) .catch(console.log) // 同步 tuaStorage.saveSync(dataToBeSaved)
还在为 web 端、小程序端、React-Native 端、node 端业务侧代码使用不同的方式调用存储层烦恼么?还在为手动数据同步,保存数据,处理过时逻辑而烦躁么?各位开发者老爷们不妨试一试 tua-storage,(挤需体验三番钟,里造会干我同样,爱象介款工具)。
inspired by react-native-storage