開門見山地說,這篇文章【又】是一篇安利軟文~,安利的對象就是 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