Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save NevenLeung/df798eb846a4d75cae7a12aec432a0ff to your computer and use it in GitHub Desktop.
Save NevenLeung/df798eb846a4d75cae7a12aec432a0ff to your computer and use it in GitHub Desktop.
some indexedDB operation wrapper
const indexedDBModule = function(dbName, version, objectStorage) {
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
const dbOpenRequest = window.indexedDB.open(dbName, version);
// 模块中的局部变量,用于存储连接成功的数据库连接
let db;
dbOpenRequest.onerror = function (event) {
console.log('Something bad happened while trying to open: ' + event.target.errorCode);
reject(event.target);
};
dbOpenRequest.onupgradeneeded = function () {
const db = dbOpenRequest.result;
// 创建存储空间,使用自增的主值
const store = db.createObjectStore(objectStorage, {
keyPath: '_id',
autoIncrement: true
});
};
dbOpenRequest.onsuccess = function () {
db = dbOpenRequest.result;
}
function useIndexedDB(action, dataParam) {
return new Promise(function(resolve, reject) {
// 创建事务
const transaction = db.transaction(objectStorage, 'readwrite');
// 在事务上得到相应的存储空间,用于数据的读取与修改
const objectStore = transaction.objectStore(objectStorage);
transaction.onabort = function (event) {
console.log('tx has been aborted.');
console.log(event.target);
};
let txOperationRequest;
switch (action) {
case 'getAll':
txOperationRequest = objectStore.getAll();
break;
case 'get':
txOperationRequest = objectStore.get(dataParam);
break;
case 'post':
txOperationRequest = objectStore.add(dataParam);
break;
case 'put':
txOperationRequest = objectStore.put(dataParam);
break;
case 'delete':
txOperationRequest = objectStore.delete(dataParam);
break;
case 'removeAll':
txOperationRequest = objectStore.clear();
}
txOperationRequest.onerror = function (event) {
console.log(event.target);
reject(event.target);
};
txOperationRequest.onsuccess = function (event) {
switch (action) {
case 'getAll':
resolve(txOperationRequest.result);
break;
case 'get':
resolve(txOperationRequest.result);
break;
case 'post':
console.log(`Item with _id ${txOperationRequest.result} has been added.`);
resolve({ _id: txOperationRequest.result});
break;
case 'put':
console.log(`Item with _id ${txOperationRequest.result} has been updated.`);
resolve({ _id: txOperationRequest.result });
break;
case 'delete':
console.log('Item has been removed.');
resolve('Item has been removed.');
break;
case 'removeAll':
console.log('All items have been removed.');
resolve('All items have been removed.');
}
};
});
};
return {
getAll: function () {
return useIndexedDB('getAll', '');
},
get: function (query) {
return useIndexedDB('get', query);
},
create: function (data) {
return useIndexedDB('post', data);
},
// update: function(query, data) {
// return useIndexedDB('get', query)
// .then(function(result) {
// if (typeof result !== 'undefined') {
// const newData = Object.assign(result, data);
// return useIndexedDB('put', newData);
// } else {
// console.log('Can not find the data according to the query');
// }
// }).catch(function(err) {
// console.error(err);
// })
// },
update: async function (query, data){
try {
const queryResult = await useIndexedDB('get', query);
if (typeof queryResult !== 'undefined') {
const newData = Object.assign(queryResult, data);
return useIndexedDB('put', newData);
} else {
console.log('Can not find the data according to the query');
}
}
catch (err) {
console.error(err);
}
},
// put: function (data) {
// return useIndexedDB('put', data);
// },
delete: function (query) {
return useIndexedDB('delete', query);
},
removeAll: function () {
return useIndexedDB('removeAll', '');
},
}
};
const todoStore = indexedDBModule('TodoApp', 1, 'todo');
// usage
// // getAll
// todoStore.getAll()
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // get
// todoStore.get(query)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // create
// todoStore.create(data)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // update
// todoStore.update(query, data)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // delete
// todoStore.delete(query)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // removeAll
// todoStore.removeAll()
// .then((result) => {
// if (result) {
// // your code
// }
// })
const indexedDBModule = function(dbName, version, objectStorage) {
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
const dbOpenRequest = window.indexedDB.open(dbName, version);
// 模块中的局部变量,用于存储连接成功的数据库连接
let db;
dbOpenRequest.onerror = function (event) {
console.log('Something bad happened while trying to open: ' + event.target.errorCode);
reject(event.target);
};
dbOpenRequest.onupgradeneeded = function () {
const db = dbOpenRequest.result;
// 创建存储空间,使用自增的主值
const store = db.createObjectStore(objectStorage, {
keyPath: '_id',
autoIncrement: true
});
};
dbOpenRequest.onsuccess = function () {
db = dbOpenRequest.result;
}
function useIndexedDB(action, dataParam) {
return new Promise(function(resolve, reject) {
// 创建事务
const transaction = db.transaction(objectStorage, 'readwrite');
// 在事务上得到相应的存储空间,用于数据的读取与修改
const objectStore = transaction.objectStore(objectStorage);
transaction.onabort = function (event) {
console.log('tx has been aborted.');
console.log(event.target);
};
let txOperationRequest;
switch (action) {
case 'getAll':
txOperationRequest = objectStore.getAll();
break;
case 'get':
txOperationRequest = objectStore.get(dataParam);
break;
case 'post':
txOperationRequest = objectStore.add(dataParam);
break;
case 'put':
txOperationRequest = objectStore.put(dataParam);
break;
case 'delete':
txOperationRequest = objectStore.delete(dataParam);
break;
case 'removeAll':
txOperationRequest = objectStore.clear();
}
txOperationRequest.onerror = function (event) {
console.log(event.target);
reject(event.target);
};
txOperationRequest.onsuccess = function (event) {
switch (action) {
case 'getAll':
resolve(txOperationRequest.result);
break;
case 'get':
resolve(txOperationRequest.result);
break;
case 'post':
console.log(`Item with _id ${txOperationRequest.result} has been added.`);
resolve({ _id: txOperationRequest.result});
break;
case 'put':
console.log(`Item with _id ${txOperationRequest.result} has been updated.`);
resolve({ _id: txOperationRequest.result });
break;
case 'delete':
console.log('Item has been removed.');
resolve('Item has been removed.');
break;
case 'removeAll':
console.log('All items have been removed.');
resolve('All items have been removed.');
}
};
});
};
return {
getAll: function () {
return useIndexedDB('getAll', '');
},
get: function (query) {
return useIndexedDB('get', query);
},
create: function (data) {
return useIndexedDB('post', data);
},
update: function(query, data) {
return useIndexedDB('get', query)
.then(function(result) {
if (typeof result !== 'undefined') {
const newData = Object.assign(result, data);
return useIndexedDB('put', newData);
} else {
console.log('Can not find the data according to the queryString');
}
}).catch(function(err) {
console.error(err);
})
},
// put: function (data) {
// return useIndexedDB('put', data);
// },
delete: function (query) {
return useIndexedDB('delete', query);
},
removeAll: function () {
return useIndexedDB('removeAll', '');
},
}
};
const todoStore = indexedDBModule('TodoApp', 1, 'todo');
// usage
// // getAll
// todoStore.getAll()
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // get
// todoStore.get(query)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // add
// todoStore.add(data)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // update
// todoStore.update(query, data)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // delete
// todoStore.delete(query)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // removeAll
// todoStore.removeAll()
// .then((result) => {
// if (result) {
// // your code
// }
// })
const todoStore = (function(dbName='TodoApp', version=1, objectStorage='todo') {
function useIndexedDB(action, dataParam) {
return new Promise(function(resolve, reject) {
const dbOpenRequest = window.indexedDB.open(dbName, version);
dbOpenRequest.onerror = function (event) {
console.log('Something bad happened while trying to open: ' + event.target.errorCode);
reject(event.target);
};
dbOpenRequest.onupgradeneeded = function () {
const db = dbOpenRequest.result;
// 创建存储空间,使用自增的主值
const store = db.createObjectStore(objectStorage, {
keyPath: '_id',
autoIncrement: true
});
};
dbOpenRequest.onsuccess = function () {
const db = dbOpenRequest.result;
// 创建事务
const transaction = db.transaction(objectStorage, 'readwrite');
// 在事务上得到相应的存储空间,用于数据的读取与修改
const objectStore = transaction.objectStore(objectStorage);
transaction.onabort = function (event) {
console.log('tx has been aborted.');
console.log(event.target);
};
let txOperationRequest;
switch (action) {
case 'getAll':
txOperationRequest = objectStore.getAll();
break;
case 'get':
txOperationRequest = objectStore.get(dataParam);
break;
case 'post':
txOperationRequest = objectStore.add(dataParam);
break;
case 'put':
txOperationRequest = objectStore.put(dataParam);
break;
case 'delete':
txOperationRequest = objectStore.delete(dataParam);
break;
case 'removeAll':
txOperationRequest = objectStore.clear();
}
txOperationRequest.onerror = function (event) {
console.log(event.target);
reject(event.target);
};
txOperationRequest.onsuccess = function (event) {
switch (action) {
case 'getAll':
resolve(txOperationRequest.result);
break;
case 'get':
resolve(txOperationRequest.result);
break;
case 'post':
console.log(`Item with _id ${txOperationRequest.result} has been added.`);
resolve({ _id: txOperationRequest.result});
break;
case 'put':
console.log(`Item with _id ${txOperationRequest.result} has been updated.`);
resolve({ _id: txOperationRequest.result });
break;
case 'delete':
console.log('Item has been removed.');
resolve('Item has been removed.');
break;
case 'removeAll':
console.log('All items have been removed.');
resolve('All items have been removed.');
}
};
transaction.oncomplete = function () {
db.close();
};
};
});
}
return {
getAll: function () {
return useIndexedDB('getAll', '');
},
get: function (queryString) {
return useIndexedDB('get', queryString);
},
add: function (data) {
return useIndexedDB('post', data);
},
update: function(queryString, data) {
return useIndexedDB('get', queryString)
.then(function(result) {
if (typeof result !== 'undefined') {
const newData = Object.assign(result, data);
return useIndexedDB('put', newData);
} else {
console.log('Can not find the data according to the queryString');
}
}).catch(function(err) {
console.error(err);
})
},
// put: function (data) {
// return useIndexedDB('put', data);
// },
delete: function (queryString) {
return useIndexedDB('delete', queryString);
},
removeAll: function () {
return useIndexedDB('removeAll', '');
},
}
}());
// usage
// // getAll
// todoStore.getAll()
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // get
// todoStore.get(queryString)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // add
// todoStore.add(data)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // update
// todoStore.update(queryString, data)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // delete
// todoStore.delete(queryString)
// .then((result) => {
// if (result) {
// // your code
// }
// })
// // removeAll
// todoStore.removeAll()
// .then((result) => {
// if (result) {
// // your code
// }
// })
// 待写入数据
const users = [
{
userID: '001',
username: 'Cherry'
},
{
userID: '002',
username: 'Rachel'
},
{
userID: '003',
username: 'Amy'
},
{
userID: '004',
username: 'david'
},
{
userID: '005',
username: 'Mia'
}
];
/**
* useIndexedDB() useIndexedDB() 利用indexedDB进行单条数据的增删改查,还支持获取或删除数据库的所有数据
*
* @param {String} action 数据库操作行为,getAll|get|add|update|remove|removeAll
* @param {String|Object} dataParam 与行为对应的数据参数
* getAll|removeAll 不需要参数,
* add|update 需要一个想要新增或更新的数据object,
* get|remove 需要一个数据库主值的value
* @param {String} dbName 数据库名称,默认为testing
* @param {Number} version 数据库版本号,为正整数,默认为1
* @param {String} objectStorageName 对象存储空间名称,相对于SQL的table name,默认为users
* @param {String} keyPath 对象存储空间的主值(对象中的属性名称),相对于table中检索使用的key,在当前对象存储空间中,对象的该属性值必须唯一,不能重复
* @param {String} accessMode 事务的访问模式,readonly|readwrite|versionchange,默认为readwrite
* @returns {Array} 返回查询行为结果的数组
*/
function useIndexedDB(action, dataParam, dbName='testing', version=1, objectStorageName='users', keyPath='userID', accessMode='readwrite') {
const result = [];
// 创建数据库连接
const request = indexedDB.open(dbName, version);
request.onerror = function (event) {
console.log('Something bad happened while trying to open: ' + event.target.errorCode);
};
request.onupgradeneeded = function () {
const db = request.result;
// 创建存储空间
const store = db.createObjectStore(objectStorageName, { keyPath: keyPath });
// const index = store.createIndex('NameIndex', 'username');
};
request.onsuccess = function () {
const db = request.result;
// 事务 - 读取与修改操作
const transaction = db.transaction(objectStorageName, accessMode);
const objectStore = transaction.objectStore(objectStorageName);
transaction.onabort = function (event) {
console.log('tx has been aborted.');
console.log(event.target);
};
// let i = 0;
// // 数据写入
// while(i < users.length) {
// const req = objectStore.put(users[i++]);
// req.onerror = function (event) {
// console.log(event.target);
// }
// }
let newRequest;
// getAll() 并不是indexedDB中的标准方法,但在当前的chrome中是可以使用的,是否增加游标查询支持
if (typeof objectStore.getAll === 'function' && action === 'getAll') {
newRequest = objectStore.getAll();
}
if (action === 'get') {
newRequest = objectStore.get(dataParam);
}
// add(),发现数据库中有一样的键值对象时,会返回一个错误,事务将会终止,可以防止数据被重新添加
// 但没关系,下一次调用dealDataWithIndexedDB()会重新建立一次数据库连接,新建一个新的事务
// 其实,使用put()也没问题,数据有更新就覆盖,没有就相对于重写一遍
// if (action === 'add') {
// newRequest = objectStore.add(dataParam);
// }
if (action === 'add' || action === 'update') {
newRequest = objectStore.put(dataParam);
}
if (action === 'remove') {
newRequest = objectStore.delete(dataParam);
}
if (action === 'removeAll') {
newRequest = objectStore.clear();
}
newRequest.onerror = function (event) {
console.log(event.target);
};
newRequest.onsuccess = function (event) {
console.log(event.target.result);
if (action === 'getAll') {
result.push(...newRequest.result);
}
if (action === 'get') {
result.push(newRequest.result);
}
};
transaction.oncomplete = function () {
db.close();
}
};
// let dataParam = dealDataWithIndexedDB('getAll');
// !似乎没问题,由于js中对象赋值为浅拷贝,等事件完成后,会往result里push数据对象,相应的更新也会给到dataParam变量。
// 潜在的风险是,数据很多,没来得及把所有数据对象push到result中,而dataParam已经被用于DOM渲染中。
return result;
}
'use strict';
// 使用回调函数处理异步操作:
// 把依赖于异步操作结果的代码以回调函数的形式传入,并将结果作为回调函数的参数执行回调函数。
// 比如,在todoList项目中,打开应用时,需要获取数据库的所有数据并渲染todoList,将渲染todoList的代码以回调形式传入useIndexedDB()中
// 待写入数据
const users = [
{
userID: '001',
username: 'Cherry'
},
{
userID: '002',
username: 'Rachel'
},
{
userID: '003',
username: 'Amy'
},
{
userID: '004',
username: 'Kilo'
},
{
userID: '005',
username: 'Mia'
}
];
let result;
useIndexedDB('getAll', '');
/**
* useIndexedDB() useIndexedDB() 利用indexedDB进行单条数据的增删改查,还支持获取或删除数据库的所有数据
*
* @param {String} action 数据库操作行为,getAll|get|add|update|remove|removeAll
* @param {String|Object} dataParam 与行为对应的数据参数
* getAll|removeAll 不需要参数,
* add|update 需要一个想要新增或更新的数据object,
* get|remove 需要一个数据库主值的value
* @param {Function} callback 回调函数
* @param {String} dbName 数据库名称,默认为testing
* @param {Number} version 数据库版本号,为正整数,默认为1
* @param {String} objectStorageName 对象存储空间名称,相对于SQL的table name,默认为users
* @param {String} keyPath 对象存储空间的主值(对象中的属性名称),相对于table中检索使用的key,在当前对象存储空间中,对象的该属性值必须唯一,不能重复
* @param {String} accessMode 事务的访问模式,readonly|readwrite|versionchange,默认为readwrite
* @returns {Array} 返回查询行为结果的数组
*/
function useIndexedDB(action, dataParam, callback=saveDataToResult, dbName='testing', version=1, objectStorageName='users', keyPath='userID', accessMode='readwrite') {
// const result = [];
// 创建数据库连接
const request = indexedDB.open(dbName, version);
request.onerror = function (event) {
console.log('Something bad happened while trying to open: ' + event.target.errorCode);
};
request.onupgradeneeded = function () {
const db = request.result;
// 创建存储空间
const store = db.createObjectStore(objectStorageName, { keyPath: keyPath });
// const index = store.createIndex('NameIndex', 'username');
};
request.onsuccess = function () {
const db = request.result;
// 事务 - 读取与修改操作
const transaction = db.transaction(objectStorageName, accessMode);
const objectStore = transaction.objectStore(objectStorageName);
transaction.onabort = function (event) {
console.log('tx has been aborted.');
console.log(event.target);
};
let i = 0;
// 初始数据写入,仅仅是为了IndexedDB中有数据可以操作,实际项目使用时,可以移除
while(i < users.length) {
const req = objectStore.put(users[i++]);
req.onerror = function (event) {
console.log(event.target);
}
}
let newRequest;
// getAll() 并不是indexedDB中的标准方法,但在当前的chrome中是可以使用的
if (typeof objectStore.getAll === 'function' && action === 'getAll') {
newRequest = objectStore.getAll();
}
if (action === 'get') {
newRequest = objectStore.get(dataParam);
}
// add()发现数据库中有一样的键值对象时,会返回一个错误,事务将会终止,可以防止数据被重新添加
// 但没关系,下一次调用dealDataWithIndexedDB()会重新建立一次数据库连接,新建一个新的事务
// 其实使用put()也没问题,数据有更新就覆盖,没有就相对于重写一遍
// 还有一个问题:只要数据对象不是完全一样,主值一样,就可以覆盖原来的数据,add和put都可以
// if (action === 'add') {
// newRequest = objectStore.add(dataParam);
// }
if (action === 'add' || action === 'update') {
newRequest = objectStore.put(dataParam);
}
if (action === 'remove') {
newRequest = objectStore.delete(dataParam);
}
if (action === 'removeAll') {
newRequest = objectStore.clear();
}
newRequest.onerror = function (event) {
console.log(event.target);
};
newRequest.onsuccess = function (event) {
// console.log(event.target.result);
if (typeof callback === 'function') {
// 先清空 result 中的的数据,确保之后只包含最新一次操作的数据
result = [];
callback(newRequest.result);
}
};
transaction.oncomplete = function () {
db.close();
};
}
}
function saveDataToResult(data) {
if (data !== null) {
Array.isArray(data) ? result.push(...data): result.push(data);
console.log(result);
}
}
'use strict';
// 使用Promise处理异步操作:
// 创建一个返回Promise的函数,在Promise的执行器中对需要的最终结果使用resolve(),在代码可能执行失败的地方,使用reject(),“返回”相应的失败信息。
// 把依赖于异步操作结果的代码以回调函数的形式传入then(),并将结果作为回调函数的参数执行回调函数。
// 待写入数据
const users = [
{
userID: '001',
username: 'Cherry'
},
{
userID: '002',
username: 'Rachel'
},
{
userID: '003',
username: 'Amy'
},
{
userID: '004',
username: 'Kilo'
},
{
userID: '005',
username: 'Mia'
}
];
let result = [];
useIndexedDB('getAll', '')
.then((query) => {
// do something with query result
result.push(...query);
console.log(result);
})
.catch((err) => {
console.log(err);
});
/**
* useIndexedDB() 利用indexedDB进行单条数据的增删改查,还支持获取或删除数据库的所有数据
*
* @param {String} action 数据库操作行为,getAll|get|add|update|remove|removeAll
* @param {String|Object} dataParam 与行为对应的数据参数
* getAll|removeAll 不需要参数,
* add|update 需要一个想要新增或更新的数据object,
* get|remove 需要一个数据库主值的value
* @returns {Promise<any>}
*/
function useIndexedDB(action, dataParam) {
return new Promise(function(resolve, reject) {
const request = indexedDB.open('testing', 1);
request.onerror = function (event) {
console.log('Something bad happened while trying to open: ' + event.target.errorCode);
reject(event.target);
};
request.onupgradeneeded = function () {
const db = request.result;
// 创建存储空间
const store = db.createObjectStore('users', { keyPath: 'userID' });
// const index = store.createIndex('NameIndex', 'username');
};
request.onsuccess = function () {
const db = request.result;
// 事务 - 读取与修改操作
const transaction = db.transaction('users', 'readwrite');
const objectStore = transaction.objectStore('users');
transaction.onabort = function (event) {
console.log('tx has been aborted.');
console.log(event.target);
};
let i = 0;
// 初始数据写入,仅仅是为了IndexedDB中有数据可以操作,实际项目使用时,可以移除
while(i < users.length) {
const req = objectStore.put(users[i++]);
req.onerror = function (event) {
console.log(event.target);
reject(event.target);
}
}
let newRequest;
// getAll() 并不是indexedDB中的标准方法,但在当前的chrome中是可以使用的
if (typeof objectStore.getAll === 'function' && action === 'getAll') {
newRequest = objectStore.getAll();
}
if (action === 'get') {
newRequest = objectStore.get(dataParam);
}
// add()发现数据库中有一样的键值对象时,会返回一个错误,事务将会终止,可以防止数据被重新添加
// 但没关系,下一次调用dealDataWithIndexedDB()会重新建立一次数据库连接,新建一个新的事务
// 其实,使用put()也没问题,数据有更新就覆盖,没有就相对于重写一遍
// 还有一个问题:只要数据对象不是完全一样,主值一样,就可以覆盖原来的数据,add和put都可以
// if (action === 'add') {
// newRequest = objectStore.add(dataParam);
// }
if (action === 'add' || action === 'update') {
newRequest = objectStore.put(dataParam);
}
if (action === 'remove') {
newRequest = objectStore.delete(dataParam);
}
if (action === 'removeAll') {
newRequest = objectStore.clear();
}
newRequest.onerror = function (event) {
console.log(event.target);
};
newRequest.onsuccess = function (event) {
// console.log(event.target.result);
if (action === 'getAll' || action === 'get') {
// result.push(...newRequest.result);
resolve(newRequest.result);
}
};
transaction.oncomplete = function () {
db.close();
};
};
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment