storage-cache.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import type { IStorageCache, StorageType, StorageValue } from './types';
  2. class StorageCache implements IStorageCache {
  3. protected prefix: string;
  4. protected storage: Storage;
  5. constructor(prefix: string = '', storageType: StorageType = 'localStorage') {
  6. this.prefix = prefix;
  7. this.storage =
  8. storageType === 'localStorage' ? localStorage : sessionStorage;
  9. }
  10. // 获取带前缀的键名
  11. private getFullKey(key: string): string {
  12. return this.prefix + key;
  13. }
  14. // 获取项之后的钩子方法
  15. protected afterGetItem<T>(_key: string, _value: T | null): void {}
  16. // 设置项之后的钩子方法
  17. protected afterSetItem<T>(
  18. _key: string,
  19. _value: T,
  20. _expiryInMinutes?: number,
  21. ): void {}
  22. // 获取项之前的钩子方法
  23. protected beforeGetItem(_key: string): void {}
  24. // 设置项之前的钩子方法
  25. protected beforeSetItem<T>(
  26. _key: string,
  27. _value: T,
  28. _expiryInMinutes?: number,
  29. ): void {}
  30. /**
  31. * 清空存储
  32. */
  33. clear(): void {
  34. try {
  35. this.storage.clear();
  36. } catch (error) {
  37. console.error('Error clearing storage', error);
  38. }
  39. }
  40. /**
  41. * 获取存储项
  42. * @param key 存储键
  43. * @returns 存储值或 null
  44. */
  45. getItem<T>(key: string): T | null {
  46. const fullKey = this.getFullKey(key);
  47. this.beforeGetItem(fullKey);
  48. let value: T | null = null;
  49. try {
  50. const item = this.storage.getItem(fullKey);
  51. if (item) {
  52. const storageValue: StorageValue<T> = JSON.parse(item);
  53. if (storageValue.expiry && storageValue.expiry < Date.now()) {
  54. this.storage.removeItem(fullKey);
  55. } else {
  56. value = storageValue.data;
  57. }
  58. }
  59. } catch (error) {
  60. console.error('Error getting item from storage', error);
  61. }
  62. this.afterGetItem(fullKey, value);
  63. return value;
  64. }
  65. /**
  66. * 获取存储中的键
  67. * @param index 键的索引
  68. * @returns 存储键或 null
  69. */
  70. key(index: number): null | string {
  71. try {
  72. return this.storage.key(index);
  73. } catch (error) {
  74. console.error('Error getting key from storage', error);
  75. return null;
  76. }
  77. }
  78. /**
  79. * 获取存储项的数量
  80. * @returns 存储项的数量
  81. */
  82. length(): number {
  83. try {
  84. return this.storage.length;
  85. } catch (error) {
  86. console.error('Error getting storage length', error);
  87. return 0;
  88. }
  89. }
  90. /**
  91. * 删除存储项
  92. * @param key 存储键
  93. */
  94. removeItem(key: string): void {
  95. const fullKey = this.getFullKey(key);
  96. try {
  97. this.storage.removeItem(fullKey);
  98. } catch (error) {
  99. console.error('Error removing item from storage', error);
  100. }
  101. }
  102. /**
  103. * 设置存储项
  104. * @param key 存储键
  105. * @param value 存储值
  106. * @param expiryInMinutes 过期时间(分钟)
  107. */
  108. setItem<T>(key: string, value: T, expiryInMinutes?: number): void {
  109. const fullKey = this.getFullKey(key);
  110. this.beforeSetItem(fullKey, value, expiryInMinutes);
  111. const now = Date.now();
  112. const expiry = expiryInMinutes ? now + expiryInMinutes * 60_000 : null;
  113. const storageValue: StorageValue<T> = {
  114. data: value,
  115. expiry,
  116. };
  117. try {
  118. this.storage.setItem(fullKey, JSON.stringify(storageValue));
  119. } catch (error) {
  120. console.error('Error setting item in storage', error);
  121. }
  122. this.afterSetItem(fullKey, value, expiryInMinutes);
  123. }
  124. }
  125. export { StorageCache };