import _get from 'lodash.get';
import _set from 'lodash.set';
import _debounce from 'lodash.debounce';
import {shallowEqual} from "./shallow-equal"; const IS_STORAGE_INITIALIZED = '$$IS_STORAGE_INITIALIZED$$'; interface PersistConfig {
save: (storageName: string, storageData: any) => void;
load: (storageName: string) => Promise<any>;
} type WatcherFn = (nextValue: any, preValue: any, storage: Storage) => void; interface Watcher {
path: string,
watcher: WatcherFn,
preValue: any
} class Storage {
private readonly storageName: string;
private storageData: Record<string, any>;
private watcherList: Watcher[];
private persistConfig: PersistConfig | null;
private readonly persistStorageFn: any; constructor(storageName: string) {
this.storageName = storageName;
this.storageData = {};
this.watcherList = []; // {path, watcher, preValue}
this.persistConfig = null; // {save:(storageName,storageData)=>{}, load:(storageName)=>{}}
this.persistStorageFn = _debounce(() => {
this.persistStorage();
}, 100);
setTimeout(() => {
this.persistStorageInit();
}, 1);
} setPersistConfig(persistConfig: PersistConfig) {
this.persistConfig = persistConfig;
} initStorageData(storageData: Record<string, any>) {
this.storageData = storageData;
this.storageData[IS_STORAGE_INITIALIZED] = true;
this.notifyWatcher();
} getValue(path: string) {
return _get(this.storageData, path);
} setValue(path: string, value: any) {
_set(this.storageData, path, value);
this.notifyWatcher();
this.persistStorageFn()
} watch(path: string, watcher: WatcherFn) {
if (typeof watcher !== "function") {
throw 'watcher must function';
}
this.watcherList.push({path, watcher, preValue: undefined});
} unwatch(path: string, watcher: WatcherFn) {
this.watcherList = this.watcherList.filter((obj) => {
return obj.path !== path && obj.watcher !== watcher;
});
} notifyWatcher() {
const watcherList = this.watcherList || [];
for (let i = 0; i < watcherList.length; i++) {
const {path, watcher, preValue} = watcherList[i];
const nextValue = this.getValue(path);
if (!shallowEqual(nextValue, preValue)) {
watcher(nextValue, preValue, this);
watcherList[i].preValue = nextValue;
}
}
} persistStorage() {
const persistConfig = this.persistConfig;
if (!persistConfig) {
return;
}
const {save} = persistConfig;
save(this.storageName, this.storageData);
} persistStorageInit() {
const persistConfig = this.persistConfig;
if (!persistConfig) {
this.initStorageData({});
return;
} const {load} = persistConfig;
load(this.storageName).then((storageData) => {
if (storageData && typeof storageData === "object") {
this.initStorageData(storageData);
} else {
this.initStorageData({});
}
}, () => {
this.initStorageData({});
});
} } class StorageManager { private storageMap: Record<string, Storage> = {}; getStorage(storageName: string) {
if (!this.storageMap[storageName]) {
this.storageMap[storageName] = new Storage(storageName);
}
return this.storageMap[storageName];
} } const storageManager = new StorageManager(); export {
storageManager,
IS_STORAGE_INITIALIZED
}

  

import localforage from '@ali/ascp-shared-local-forage'

/**
* 使用 localStorage 存储
*/
const localStoragePersist = {
save: (storageName, storageData) => {
localStorage.setItem(storageName, JSON.stringify(storageData));
},
load: (storageName) => {
return new Promise((resolve) => {
const str = localStorage.getItem(storageName);
if (str) {
resolve(JSON.parse(str))
} else {
resolve(null);
}
})
}
} /**
* 使用 localforage 存储
*/
const localForagePersist = {
save: (storageName, storageData) => {
localforage.setItem(storageName, storageData);
},
load: (storageName) => {
return localforage.getItem(storageName);
}
}; export {
localStoragePersist,
localForagePersist
}
import {useEffect, useState} from 'react';
import {storageManager} from "../utils/storage"; function useStorageValue(storageName, persistConfig, path) { const storage = storageManager.getStorage(storageName);
storage.setPersistConfig(persistConfig) const [value, setValue] = useState(() => {
return storage.getValue(path);
}); useEffect(() => { const watcher = (nowValue) => {
setValue(nowValue);
}; storage.watch(path, watcher); return () => {
storage.unwatch(path, watcher);
} }, [storageName, path]); return value;
} export {
useStorageValue
}

  

[js函数] storageManager的更多相关文章

  1. 3.3 js函数

    1.函数语法: 函数声明的方式:function 函数名(参数1,参数2-){//函数体;}函数调用:函数名(参数1,参数2-); 函数内不一定都指定返回值. 如果需要指定返回值,可用 return ...

  2. Js函数function基础理解

    正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定 ...

  3. js函数表达式和函数声明的区别

    我们已经知道,在任意代码片段外部添加包装函数,可以将内部的变量和函数定义"隐 藏"起来,外部作用域无法访问包装函数内部的任何内容. 例如: var a = 2; function ...

  4. 通用js函数集锦<来源于网络> 【二】

    通用js函数集锦<来源于网络> [二] 1.数组方法集2.cookie方法集3.url方法集4.正则表达式方法集5.字符串方法集6.加密方法集7.日期方法集8.浏览器检测方法集9.json ...

  5. 通用js函数集锦<来源于网络/自己> 【一】

    通用js函数集锦<来源于网络/自己>[一] 1.返回一个全地址2.cookie3.验证用户浏览器是否是微信浏览器4.验证用户浏览器是否是微博内置浏览器5.query string6.验证用 ...

  6. 100多个基础常用JS函数和语法集合大全

    网站特效离不开脚本,javascript是最常用的脚本语言,我们归纳一下常用的基础函数和语法: 1.输出语句:document.write(""); 2.JS中的注释为//3.传统 ...

  7. JS函数

    1.document.write(""); 输出语句2.JS中的注释为//3.传统的HTML文档顺序是:document->html->(head,body)4.一个浏 ...

  8. js函数和运算符

    函数是由事件驱动或者它被调用时执行可重复使用的代码块. <script> function myFunction(){ Alert(“hello World!”): } </scri ...

  9. JavaScript学习03 JS函数

    JavaScript学习03 JS函数 函数就是包裹在花括号中的代码块,前面使用了关键词function: function functionName() { 这里是要执行的代码 } 函数参数 函数的 ...

  10. JSF页面中使用js函数回调后台bean方法并获取返回值的方法

    由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的, ...

随机推荐

  1. 接口自动化库-apist

    前言 目前很多公司用jmeter或者RF框架来实现接口自动化,确实是可以实现,但不利于CI/CD. 为了方便后续的可拓展性.可维护性.可复用性,项目leader在技术选型的时候应当以趋势.主流的为主, ...

  2. Os-hackNos-3

    Os-hackNos-3 目录 Os-hackNos-3 1 信息收集 1.1 端口扫描 1.2 后台目录扫描 1.2.1 目录分析 2 爆破后台登录页面 2.1 BP爆破 2.2 hydra爆破 3 ...

  3. 自己动手从零写桌面操作系统GrapeOS系列教程——6.电脑启动过程介绍

    学习操作系统原理最好的方法是自己写一个简单的操作系统. 按一下电脑上的电源按钮,电脑就启动了,不一会儿电脑屏幕上就出现了登录界面或直接进入了桌面. 这是一个很日常的场景,但有时候会有个疑问:电脑内部是 ...

  4. 聊一下kafka的消费组

    介绍 消费组使kafka中很重的概念,只有弄清楚消费组的概念,才能在项目中把它运用好,在kafka中,每个消费者都对应一个消费组,消费者可以是一个线程,一个进程,一个服务实例,如果kafka想要消费消 ...

  5. JavaScrip 学习笔记

    <script> $().ready(function () { // 在键盘按下并释放及提交后验证提交表单 $("#form1").validate({ errorE ...

  6. K8s之Etcd的备份与恢复

    ETCD简介 ETCD用于共享和配置服务发现的分布式,一致性的KV存储系统. ETCD是CoreOS公司发起的一个开源项目,授权协议为Apache. ETCD 存储 k8s 所有数据信息 ETCD 是 ...

  7. scrapy 爬取酷狗热门歌手音乐

    目录 声明 Hello,酷狗! 创建一个Scrapy项目 spider模块 分析前端界面 注意 items模块 pipeline模块 处理音频文件自定义下载路径 自定义下载图片路径 异步存入到数据库 ...

  8. Spring的AOP源码解析(一)

    Spring AOP 使用介绍,从前世到今生 前面写过 Spring IOC 的源码分析,很多读者希望可以出一个 Spring AOP 的源码分析,不过 Spring AOP 的源码还是比较多的,写出 ...

  9. js 字符串中提取ip地址

    方法1: var reg = new RegExp(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);var str = 'http://172.38.172.10:8000 ...

  10. 获取Java运行环境信息

    设备相关信息 获取设备名称 import java.net.InetAddress; import java.net.UnknownHostException; try { InetAddress l ...