storage-manager.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. type StorageType = 'localStorage' | 'sessionStorage';
  2. interface StorageManagerOptions {
  3. prefix?: string;
  4. storageType?: StorageType;
  5. }
  6. interface StorageItem<T> {
  7. expiry?: number;
  8. value: T;
  9. }
  10. class StorageManager {
  11. private prefix: string;
  12. private storage: Storage;
  13. constructor({
  14. prefix = '',
  15. storageType = 'localStorage',
  16. }: StorageManagerOptions = {}) {
  17. this.prefix = prefix;
  18. this.storage =
  19. storageType === 'localStorage'
  20. ? window.localStorage
  21. : window.sessionStorage;
  22. }
  23. /**
  24. * 获取完整的存储键
  25. * @param key 原始键
  26. * @returns 带前缀的完整键
  27. */
  28. private getFullKey(key: string): string {
  29. return `${this.prefix}-${key}`;
  30. }
  31. /**
  32. * 清除所有带前缀的存储项
  33. */
  34. clear(): void {
  35. const keysToRemove: string[] = [];
  36. for (let i = 0; i < this.storage.length; i++) {
  37. const key = this.storage.key(i);
  38. if (key && key.startsWith(this.prefix)) {
  39. keysToRemove.push(key);
  40. }
  41. }
  42. keysToRemove.forEach((key) => this.storage.removeItem(key));
  43. }
  44. /**
  45. * 清除所有过期的存储项
  46. */
  47. clearExpiredItems(): void {
  48. for (let i = 0; i < this.storage.length; i++) {
  49. const key = this.storage.key(i);
  50. if (key && key.startsWith(this.prefix)) {
  51. const shortKey = key.replace(this.prefix, '');
  52. this.getItem(shortKey); // 调用 getItem 方法检查并移除过期项
  53. }
  54. }
  55. }
  56. /**
  57. * 获取存储项
  58. * @param key 键
  59. * @param defaultValue 当项不存在或已过期时返回的默认值
  60. * @returns 值,如果项已过期或解析错误则返回默认值
  61. */
  62. getItem<T>(key: string, defaultValue: T | null = null): T | null {
  63. const fullKey = this.getFullKey(key);
  64. const itemStr = this.storage.getItem(fullKey);
  65. if (!itemStr) {
  66. return defaultValue;
  67. }
  68. try {
  69. const item: StorageItem<T> = JSON.parse(itemStr);
  70. if (item.expiry && Date.now() > item.expiry) {
  71. this.storage.removeItem(fullKey);
  72. return defaultValue;
  73. }
  74. return item.value;
  75. } catch (error) {
  76. console.error(`Error parsing item with key "${fullKey}":`, error);
  77. this.storage.removeItem(fullKey); // 如果解析失败,删除该项
  78. return defaultValue;
  79. }
  80. }
  81. /**
  82. * 移除存储项
  83. * @param key 键
  84. */
  85. removeItem(key: string): void {
  86. const fullKey = this.getFullKey(key);
  87. this.storage.removeItem(fullKey);
  88. }
  89. /**
  90. * 设置存储项
  91. * @param key 键
  92. * @param value 值
  93. * @param ttl 存活时间(毫秒)
  94. */
  95. setItem<T>(key: string, value: T, ttl?: number): void {
  96. const fullKey = this.getFullKey(key);
  97. const expiry = ttl ? Date.now() + ttl : undefined;
  98. const item: StorageItem<T> = { expiry, value };
  99. try {
  100. this.storage.setItem(fullKey, JSON.stringify(item));
  101. } catch (error) {
  102. console.error(`Error setting item with key "${fullKey}":`, error);
  103. }
  104. }
  105. }
  106. export { StorageManager };