在前面的一篇文章中,我们已经实现了使用indexedDB实现ajax本地数据存储的功能,详情,请看这篇文章。现在我们需要把上面的一篇文章中的代码使用promise结构来重构下。我们为什么需要使用promise来重构呢?我们之前一直使用 indexedDB中的代码,但是在indexedDB中,我们代码很大程度上依赖于回调,如果我们的代码越来越多,我们需要的回调嵌套就越来越多,这对于后期代码维护不是很好。
比如我们可以看看我们之前的代码如下所示:
// 打开或创建 store-data 数据库 var result = window.indexedDB.open('store-data', 3); // 监听error函数触发 result.onerror = function(event) { console.log("DataBase error:", event.target.error); } // 监听当前版本号被升级的时候触发该函数 result.onupgradeneeded = function(event) { var db = event.target.result; /* 是否包含该对象仓库名(或叫表名)。如果不包含就创建一个。 该对象中的 keyPath属性id为主键 */ if (!db.objectStoreNames.contains('store')) { db.createObjectStore("store", { keyPath: "id", autoIncrement: true }); } } result.onsuccess = function(event) { var targetValue = event.target.result; /* 1. 使用 targetValue.transaction(storeName, transactionMode) 来创建事务 2. 创建事务之后,我们使用 targetValue.transaction(storeName, transactionMode).objectStore(storeName) 这个方法,拿到 IDBObjectStore对象。 */ var objectStore = targetValue.transaction(storeName, transactionMode).objectStore(storeName); var request = objectStore.add({id: 3, name: 'kongzhi12', age: 31}); request.onsuccess = function(event) { console.log('回调函数成功'); } request.onerror = function(event) { console.log("DataBase error:", event.target.error); } }
如上代码,我们打开了或创建了一个 store-data 数据库,然后把onsuccess回调附加到该请求上,在该onsuccess请求上,我们又有请求事件,接着有 onsuccess 回调函数,依次类推,如果以后代码越来越复杂的时候,我们以后代码就一直变成回调嵌套中,因此我们现在想使用promise方法来重构上面的代码,我们想要让上面的代码变成如下所示这样的:
openDatabase('store-data', 3).then(function(db) { return openObjectStore(db, "store", "readwrite"); }).then(function(objectStore){ return addObject(objectStore, {"id": 3, "name": 'kongzhi123', 'age': 31}); }).then(function(){ console.log('回调成功'); }).catch(function(error) { console.log('DataBase error', error); });
我们希望变成如上的promise代码,我们希望将javascript异步回调的代码变成我们的promise代码。在重构我们的代码之前,我们先来看看我们的 XMLHttpRequest 代码,我们希望使用promise来重构该代码,在重构之前,我们先来看看XMLHttpRequest代码如下:
var xhr = new XMLHttpRequest(); xhr.onload = function() { // 处理响应 }; xhr.onerror = function() { // 处理错误 }; xhr.open("get", '/xxx.json', true); xhr.send();
如上这样的代码,是我们之前的xmlHttpRequest代码,现在我们可以使用我们的promise来重构我们上面的代码,因此重构后的代码变成如下所示:
var promise_XHR = function(url, method) { return new Promise(function(resolve, reject) { var xhr = new XMLHttpRequest(); xhr.onload = resolve; xhr.onerror = reject; xhr.open(method, url, true); xhr.send(); }); };
如上 promise_XHR 函数,该函数接收一个url 和 method参数,并返回了一个promise对象,该promise传入了一个函数,该函数有两个参数,代表成功和失败的回调,然后内部代码,我们创建了一个XMLHttpRequest对象,然后该对象 onload 函数的时候 把resolve 成功回调赋值给他,然后 xhr.onerror 函数的时候,把 reject 拒绝函数传递给他,我们调用方式如下所示:
promise_XHR('/xxx.json', 'get').then(function(){ // 处理成功的回调函数 }).catch(error) { // 处理我们异常的回调函数 }
现在我们想把该方式使用到我们的 store.js 代码内部来。重构后的代码就变成了如下:
import axios from 'axios'; var DB_VERSION = 1; var DB_NAME = 'store-data2'; var openDataBase = function() { return new Promise(function(resolve, reject) { if (!window.indexedDB) { reject("indexedDB not supported"); } // 打开或创建 store-data 数据库 var result = window.indexedDB.open(DB_NAME, DB_VERSION); // 监听error函数触发 result.onerror = function(event) { console.log("DataBase error:", event.target.error); } // 监听当前版本号被升级的时候触发该函数 result.onupgradeneeded = function(event) { var db = event.target.result; /* 是否包含该对象仓库名(或叫表名)。如果不包含就创建一个。 该对象中的 keyPath属性id为主键 */ if (!db.objectStoreNames.contains('store')) { db.createObjectStore("store", { keyPath: "id", autoIncrement: true }); } } result.onsuccess = function(event) { resolve(event.target.result); } }); }; /* @param {storeName} 仓库名或表名 @param {transactionMode} 事务模式 readOnly 只读,readwrite 可读可写 */ var openObjectStore = function(db, storeName, transactionMode) { return db.transaction(storeName, transactionMode).objectStore(storeName); }; var getStore = function (successCallback) { return new Promise(function(resolve, reject) { openDataBase().then(function(db) { var objectStore = openObjectStore(db, 'store'); var datas = []; objectStore.openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { datas.push(cursor.value); cursor.continue(); } else { if (datas.length > 0) { resolve(datas); } else { getDataFromServer().then(function(d) { openDataBase().then(function(db) { var objectStore = openObjectStore(db, "store", "readwrite"); for (let i = 0; i < datas.length; i++) { objectStore.add(datas[i]); } resolve(datas); }); }); } } } }).catch(function() { getDataFromServer().then(function(datas) { resolve(datas); }); }); }); }; function getDataFromServer() { return new Promise(function(resolve, reject) { axios.get("http://localhost:8081/public/json/index.json", resolve); }); } var addToObjectStore = function(storeName, object) { return new Promise(function(resolve, reject) { openDataBase().then(function(db) { openObjectStore(db, storeName, 'readwrite').add(object).onsuccess = resolve; }).catch(function(error) { reject(error); }) }); }; var updateInObjectStore = function(storeName, id, object) { return new Promise(function(resolve, reject) { openDataBase().then(function(db) { openObjectStore(db, storeName, "readwrite").openCursor().onsuccess = function(event) { var cursor = event.target.result; if (!cursor) { reject("store-data not found"); } if (cursor.value.id === id) { cursor.put(object).onsuccess = resolve; return; } cursor.continue(); } }).catch(function(){ reject(error); }) }); } window.openDataBase = openDataBase; window.openObjectStore = openObjectStore; window.addToObjectStore = addToObjectStore; window.updateInObjectStore = updateInObjectStore; window.getStore = getStore;
然后我们需要在我们的 myAccount.js 代码改成如下初始化所示:
import $ from 'jquery'; $(function() { openDataBase("store-data2", 2).then(function(db) { return openObjectStore(db, "store", "readwrite"); }).then(function(objectStore) { return addToObjectStore("store", {id: 1, name: 'kongzhi111', age: 11}); }).then(function() { console.log('添加成功'); }).catch(function(error) { console.log("数据库加载失败", error); }); /* var addStore = function(id, name, age) { var obj = { id: id, name: name, age: age }; addToObjectStore("store", obj); renderHTMLFunc(obj); $.getJSON("http://localhost:8081/public/json/index.json", obj, function(data) { updateDisplay(data); }); }; $("#submit").click(function(e) { addStore(3, 'longen1', '111'); }); $("#update").click(function(e) { $.getJSON("http://localhost:8081/public/json/index.json", {id: 1}, function(data) { updateInObjectStore("store", 1, data); updateDisplay(data); }); }); */ });
然后会向我们的数据库中插入一条数据,我们刷新页面后查看我们的本地数据库如下所示:
github源码demo查看