IndexedDB.ts 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. export default class IndexedDB {
  2. private dbName: string;
  3. private storeName: string;
  4. private dbVersion: number = 1;
  5. constructor(dbName: string, storeName: string, version?: number) {
  6. this.dbName = dbName;
  7. this.storeName = storeName;
  8. if (version) this.dbVersion = version;
  9. }
  10. //打开数据库
  11. private openDatabase(retryCount: number = 3, delay: number = 300): Promise<IDBDatabase> {
  12. return new Promise<IDBDatabase>((resolve, reject) => {
  13. const tryOpen = (attempt: number) => {
  14. const request = window.indexedDB.open(this.dbName, this.dbVersion);
  15. request.onupgradeneeded = (event) => {
  16. const target = event.target as IDBOpenDBRequest;
  17. const db = target.result;
  18. if (!db.objectStoreNames.contains(this.storeName)) {
  19. const store = db.createObjectStore(this.storeName, { keyPath: 'key' });
  20. store.createIndex('valueIndex', 'value', { unique: false });
  21. }
  22. };
  23. request.onsuccess = (event) => {
  24. const target = event.target as IDBOpenDBRequest;
  25. resolve(target.result);
  26. };
  27. request.onerror = (event) => {
  28. const target = event.target as IDBOpenDBRequest;
  29. if (attempt < retryCount) {
  30. console.warn(`数据库打开失败,第${attempt}次重试...`);
  31. setTimeout(() => tryOpen(attempt + 1), delay);
  32. } else {
  33. reject(new Error(`数据库打开失败(重试${retryCount}次): ${target.error}`));
  34. }
  35. };
  36. };
  37. tryOpen(1);
  38. });
  39. }
  40. /**
  41. * 设置数据 (使用字符串key)
  42. */
  43. // 在setData等方法中添加事务错误处理
  44. setData(key: string, value: any): Promise<void> {
  45. return new Promise<void>((resolve, reject) => {
  46. this.openDatabase()
  47. .then((db) => {
  48. const transaction = db.transaction([this.storeName], 'readwrite');
  49. transaction.onerror = () => reject(new Error('Transaction failed: ' + transaction.error));
  50. const objectStore = transaction.objectStore(this.storeName);
  51. const request = objectStore.put({ key, value });
  52. request.onsuccess = () => resolve();
  53. request.onerror = () => reject(new Error('Failed to set data: ' + request.error));
  54. })
  55. .catch(reject);
  56. });
  57. }
  58. /**
  59. * 批量设置数据
  60. * @param items 键值对数组,格式为 {key: string, value: any}[]
  61. */
  62. setBatchData(items: { key: string, value: any }[]): Promise<void> {
  63. return new Promise<void>((resolve, reject) => {
  64. this.openDatabase()
  65. .then((db) => {
  66. const transaction = db.transaction([this.storeName], 'readwrite');
  67. const objectStore = transaction.objectStore(this.storeName);
  68. // 批量添加/更新数据
  69. items.forEach(item => {
  70. objectStore.put({ key: item.key, value: item.value });
  71. });
  72. transaction.oncomplete = () => resolve();
  73. transaction.onerror = () =>
  74. reject(new Error('Failed to set batch data: ' + transaction.error));
  75. })
  76. .catch(reject);
  77. });
  78. }
  79. /**
  80. * 获取数据 (使用字符串key)
  81. */
  82. getData(key: string): Promise<any> {
  83. return new Promise<any>((resolve, reject) => {
  84. this.openDatabase()
  85. .then((db) => {
  86. const transaction = db.transaction([this.storeName], 'readonly');
  87. const objectStore = transaction.objectStore(this.storeName);
  88. const request = objectStore.get(key);
  89. request.onsuccess = () => resolve(request.result?.value);
  90. request.onerror = () => reject(new Error('Failed to get data: ' + request.error));
  91. })
  92. .catch(reject);
  93. });
  94. }
  95. /**
  96. * 删除数据 (使用字符串key)
  97. * @param key
  98. * @returns
  99. */
  100. deleteData(key: string): Promise<void> {
  101. return new Promise<void>((resolve, reject) => {
  102. this.openDatabase()
  103. .then((db) => {
  104. const transaction = db.transaction([this.storeName], 'readwrite');
  105. const objectStore = transaction.objectStore(this.storeName);
  106. const request = objectStore.delete(key);
  107. request.onsuccess = () => resolve();
  108. request.onerror = () => reject(new Error('Failed to delete data: ' + request.error));
  109. })
  110. .catch(reject);
  111. });
  112. }
  113. /**
  114. *清空表数据
  115. * @returns
  116. */
  117. clearAll(): Promise<void> {
  118. return new Promise<void>((resolve, reject) => {
  119. this.openDatabase()
  120. .then((db) => {
  121. const transaction = db.transaction([this.storeName], 'readwrite');
  122. const objectStore = transaction.objectStore(this.storeName);
  123. const request = objectStore.clear();
  124. request.onsuccess = () => resolve();
  125. request.onerror = () => reject(new Error('Failed to clear all data: ' + request.error));
  126. })
  127. .catch(reject);
  128. });
  129. }
  130. /**
  131. * 按索引查询数据
  132. * @param indexName 索引名称
  133. * @param value 索引值
  134. */
  135. getDataByIndex(indexName: string, value: any): Promise<any[]> {
  136. return new Promise<any[]>((resolve, reject) => {
  137. this.openDatabase()
  138. .then((db) => {
  139. const transaction = db.transaction([this.storeName], 'readonly');
  140. const objectStore = transaction.objectStore(this.storeName);
  141. const index = objectStore.index(indexName);
  142. const request = index.getAll(value);
  143. request.onsuccess = () => resolve(request.result);
  144. request.onerror = () => reject(new Error('Failed to get data by index: ' + request.error));
  145. })
  146. .catch(reject);
  147. });
  148. }
  149. /**
  150. * 获取所有数据
  151. */
  152. getAllData(): Promise<any[]> {
  153. return new Promise<any[]>((resolve, reject) => {
  154. this.openDatabase()
  155. .then((db) => {
  156. const transaction = db.transaction([this.storeName], 'readonly');
  157. const objectStore = transaction.objectStore(this.storeName);
  158. const request = objectStore.getAll();
  159. request.onsuccess = () => resolve(request.result);
  160. request.onerror = () => reject(new Error('Failed to get all data: ' + request.error));
  161. })
  162. .catch(reject);
  163. });
  164. }
  165. /**
  166. * 获取数据总数
  167. */
  168. count(): Promise<number> {
  169. return new Promise<number>((resolve, reject) => {
  170. this.openDatabase()
  171. .then((db) => {
  172. const transaction = db.transaction([this.storeName], 'readonly');
  173. const objectStore = transaction.objectStore(this.storeName);
  174. const request = objectStore.count();
  175. request.onsuccess = () => resolve(request.result);
  176. request.onerror = () => reject(new Error('Count error: ' + request.error));
  177. })
  178. .catch(reject);
  179. });
  180. }
  181. /**
  182. * 使用游标遍历所有数据
  183. * @param callback 处理每条数据的回调函数
  184. */
  185. forEach(callback: (value: any, key: string) => boolean | void): Promise<void> {
  186. return new Promise<void>((resolve, reject) => {
  187. this.openDatabase()
  188. .then((db) => {
  189. const transaction = db.transaction([this.storeName], 'readonly');
  190. const objectStore = transaction.objectStore(this.storeName);
  191. const request = objectStore.openCursor();
  192. request.onsuccess = (event) => {
  193. const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;
  194. if (cursor) {
  195. const shouldContinue = callback(cursor.value.value, cursor.value.key);
  196. if (shouldContinue !== false) {
  197. cursor.continue();
  198. }
  199. } else {
  200. resolve();
  201. }
  202. };
  203. request.onerror = () => reject(new Error('Cursor error: ' + request.error));
  204. })
  205. .catch(reject);
  206. });
  207. }
  208. }
  209. /*
  210. // 使用示例
  211. const storage = new IndexedDB('myDatabase', 'myStore');
  212. // 清空表数据
  213. storage.clearAll()
  214. .then(() => console.log('All data cleared successfully'))
  215. .catch(err => console.error('Error clearing data:', err));
  216. // 保存数据
  217. storage.setData('user1', { name: 'John', age: 30 })
  218. .then(() => console.log('Data saved successfully'))
  219. .catch(err => console.error('Error saving data:', err));
  220. // 获取数据
  221. storage.getData('user1')
  222. .then(data => console.log('Retrieved data:', data))
  223. .catch(err => console.error('Error retrieving data:', err));
  224. */