packages/render/miniapp/apiForH5/storage.js
const ERROR_MESSAGE = '不支持 localStorage !';
import { handleSuccess, handleFail } from '../utils';
function isSupportStorage() {
if (!window.localStorage) {
// eslint-disable-next-line no-console
console.log(ERROR_MESSAGE);
return false;
}
return true;
}
/**
* 将数据储存在浏览器中指定的 key 中,会覆盖掉原来该 key 对应的内容
* @method setStorage
* @param {String} key 缓存中指定的 key
* @param {Object/String} data 需要存储的内容
*/
function setStorage({
key,
data,
success = () => {},
fail = () => {},
complete = () => {}
} = {}) {
return new Promise((resolve, reject) => {
if (!isSupportStorage()) {
handleFail({ errMsg: ERROR_MESSAGE }, fail, complete, reject);
} else {
localStorage.setItem(key, JSON.stringify(data));
handleSuccess({ key, data }, success, complete, resolve);
}
});
}
/**
* setStorage 的同步版本
* @method setStorageSync
* @param {String} key 缓存中指定的 key
* @param {Object/String} data 需要存储的内容
*/
function setStorageSync(key, data) {
if (!isSupportStorage()) {
return;
}
localStorage.setItem(key, JSON.stringify(data));
}
/**
* 获取缓存数据
* @method getStorage
* @param {String} key 缓存中指定的 key
*/
function getStorage({
key,
success = () => {},
fail = () => {},
complete = () => {}
} = {}) {
return new Promise((resolve, reject) => {
if (!isSupportStorage()) {
handleFail({ errMsg: ERROR_MESSAGE }, fail, complete, reject);
} else {
handleSuccess(
{ data: JSON.parse(localStorage.getItem(key)) },
success,
complete,
resolve
);
}
});
}
/**
* getStorage 的同步版本
* @method getStorageSync
* @param {String} key 缓存中指定的 key
* @return {Object/String} key 对应的数据
*/
function getStorageSync(key) {
if (!isSupportStorage()) {
return;
}
return JSON.parse(localStorage.getItem(key));
}
/**
* 从缓存中移除指定 key
* @method removeStorage
* @param {String} key 缓存中指定的 key
*/
function removeStorage({
key,
success = () => {},
fail = () => {},
complete = () => {}
} = {}) {
return new Promise((resolve, reject) => {
if (!isSupportStorage()) {
handleFail({ errMsg: ERROR_MESSAGE }, fail, complete, reject);
} else {
localStorage.removeItem(key);
handleSuccess(null, success, complete, resolve);
}
});
}
/**
* removeStorage 的同步版本
* @method removeStorageSync
* @param {String} key 缓存中指定的 key
*/
function removeStorageSync(key) {
if (!isSupportStorage()) {
return;
}
localStorage.removeItem(key);
}
/**
* 清空缓存数据
* @method clearStorage
*/
function clearStorage({
success = () => {},
fail = () => {},
complete = () => {}
} = {}) {
return new Promise((resolve, reject) => {
if (!isSupportStorage()) {
handleFail({ errMsg: ERROR_MESSAGE }, fail, complete, reject);
} else {
localStorage.clear();
handleSuccess(null, success, complete, resolve);
}
});
}
/**
* clearStorage 的同步版本
* @method clearStorageSync
*/
function clearStorageSync() {
if (!isSupportStorage()) {
return;
}
localStorage.clear();
}
// 返回 10KB 大小的字符串
function get10KBStr() {
let str = '0123456789';
function add(s) {
s += str;
if (s.length === 10240) {
str = s;
return;
}
add(s);
}
add(str);
return str;
}
let LIMIT_SIZE_CACHE = -1;
// 获取 localStorage 剩余容量 KB
function getStorageUnusedSize(cb) {
if (LIMIT_SIZE_CACHE !== -1) {
cb(LIMIT_SIZE_CACHE);
} else {
const _10KBStr = get10KBStr();
let sum = _10KBStr;
const id = setInterval(function() {
sum += _10KBStr;
try {
localStorage.removeItem('test');
localStorage.setItem('test', sum);
} catch (e) {
LIMIT_SIZE_CACHE = sum.length / 1024;
cb(LIMIT_SIZE_CACHE);
clearInterval(id);
}
}, 1);
}
}
// 获取 localStorage 使用容量 KB
// 有个奇怪的问题,localStorage.setItem('length', 100)
// localStorage.valueOf() 或 Object.keys(localStorage) 里并没有 length
// 只能使用 localStorage.getItem('length')获取到
function getStorageUsedSize() {
const values = Object.values(localStorage.valueOf());
return values.reduce((size, value) => value.length, 0) / 1024;
}
/**
* getStorageInfo 的同步版本
* @method getStorageInfoSync
* @param {Boolean} [needLimitSize=false] 是否需要 storage 限制的空间大小
* @return {Object} keys,currentSize,limitSize
*/
async function getStorageInfoSync(needLimitSize = false) {
const result = await getStorageInfo({ needLimitSize });
return result;
}
/**
* 获取当前 storage 的相关信息
* 由于 limitSize 采用的是不断向 storage 添加直至添满来得到的,耗费性能和时间(只在第一次,之后使用缓存值),所以需要的时候传入 needLimitSize 为 true
* 第一次要等待 10多秒。。。
* @method getStorageInfo
* @param {Boolean} needLimitSize 是否需要 storage 限制的空间大小
*/
function getStorageInfo({
needLimitSize = false,
success = () => {},
fail = () => {},
complete = () => {}
} = {}) {
return new Promise((resolve, reject) => {
if (!isSupportStorage()) {
handleFail({ errMsg: ERROR_MESSAGE }, fail, complete, reject);
return;
}
const result = {
keys: Object.keys(localStorage),
currentSize: getStorageUsedSize()
};
if (needLimitSize) {
getStorageUnusedSize(unUsedSize => {
handleSuccess(
{
...result,
limitSize: result.currentSize + unUsedSize
},
success,
complete,
resolve
);
});
} else {
handleSuccess(result, success, complete, resolve);
}
});
}
export default {
setStorage,
setStorageSync,
getStorage,
getStorageSync,
removeStorage,
removeStorageSync,
clearStorage,
clearStorageSync,
getStorageInfo,
getStorageInfoSync
};