在前面的一篇文章中,我们已经实现了使用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查看

渐进式web应用开发---promise式数据库(五)的更多相关文章

  1. 渐进式web应用开发---service worker 原理及介绍(一)

    渐进式web应用(progressive Web app) 是现代web应用的一种新形式.它利用了最新的web功能,结合了原生移动应用的独特特性与web的优点,为用户带来了新的体验. 一:传统web端 ...

  2. 渐进式web应用开发-- 使用后台同步保证离线功能(六)

    _ 阅读目录 一:什么是后台同步保证离线功能呢? 二:后台同步是如何实现的呢? 三:如何给sync事件传递数据? 四:在我们的项目中添加后台同步功能 回到顶部 一:什么是后台同步保证离线功能呢? 在我 ...

  3. 渐进式web应用开发--拥抱离线优先(三)

    _ 阅读目录 一:什么是离线优先? 二:常用的缓存模式 三:混合与匹配,创造新模式 四:规划缓存策略 五:实现缓存策略 回到顶部 一:什么是离线优先? 传统的web应用完全依赖于服务器端,比如像很早以 ...

  4. 渐进式web应用开发---Service Worker 与页面通信(七)

    _ 阅读目录 一:页面窗口向 service worker 通信 二:service worker 向所有打开的窗口页面通信 三:service worker 向特定的窗口通信 四:学习 Messag ...

  5. 渐进式web应用开发---service worker (二)

    阅读目录 1. 创建第一个service worker 及环境搭建 2. 使用service worker 对请求拦截 3. 从web获取内容 4. 捕获离线请求 5. 创建html响应 6. 理解 ...

  6. 渐进式web应用开发---ajax本地数据存储(四)

    在前几篇文章中,我们使用service worker一步步优化了我们的页面,现在我们学习使用我们之前的indexedDB, 来缓存我们的ajax请求,第一次访问页面的时候,我们请求ajax,当我们继续 ...

  7. 渐进式web应用开发---使用indexedDB实现ajax本地数据存储(四)

    在前几篇文章中,我们使用service worker一步步优化了我们的页面,现在我们学习使用我们之前的indexedDB, 来缓存我们的ajax请求,第一次访问页面的时候,我们请求ajax,当我们继续 ...

  8. Java Web程序开发链接MySQL数据库

    显示错误:Access denied for user ''@'localhost' (using password: YES) 保证URL中没有空格 尝试用MySQL本地命令行登陆 显示错误:The ...

  9. (数据科学学习手札118)Python+Dash快速web应用开发——特殊部件篇

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

随机推荐

  1. UWP入门(四)--设置控件样式

    原文:UWP入门(四)--设置控件样式 官方定义:可以使用 XAML 框架通过多种方式自定义应用的外观. 通过样式可以设置控件属性,并重复使用这些设置,以便保持多个控件具有一致的外观. 可分享至不同e ...

  2. C++开源库,欢迎补充

    C++在“商业应用”方面,曾经是天下第一的开发语言,但这一桂冠已经被java抢走多年.因为当今商业应用程序类型,已经从桌面应用迅速转移成Web应 用.当Java横行天下之后,MS又突然发力,搞出C#语 ...

  3. 【Web前端Talk】React-loadable 进行代码分割的基本使用

    随着项目功能的扩充.版本迭代,我们与Webpack捆绑起来的的项目越来越大,大到开始影响加载速度了.这时我们就该考虑如何对代码进行拆分了. 这次我们一起学习一下如何对React项目中的代码进行Code ...

  4. hadoop之hive高级操作

    在输出结果较多,需要输出到文件中时,可以在hive CLI之外执行hive -e "sql" > output.txt操作 但当SQL语句太长或太多时,这种方式不是很方便,可 ...

  5. Python时间戳的一些使用

    Python时间戳的一些使用 为什么写下这篇文档? 由于我本身是做Python爬虫的,在爬取网站的过程当中,会遇到形形色色的验证码,目前对于自己而言,可能简单的验证码可以进行自己识别 发现大多数的网站 ...

  6. 戏说 .NET GDI+系列学习教程(一、Graphics类--纸)

    Graphics类(纸) Graphics类封装一个GDI+绘图图面,提供将对象绘制到显示设备的方法,Graphics与特定的设备上下文关联. 画图方法都被包括在Graphics类中,在画任何对象时, ...

  7. 模块化 require.js 入门教学(前端必看系列)

    在工作的时候总是会用到模块化开发,那接下来我就顺着这个问题来说一下什么是模块化 前端模块化 !!! JS 模块化提供给我们三种规范 分别就是 No.1 commonjs  这个其实也就代表了node. ...

  8. 如何用css实线所需要的小三角

    使用css实现三角符号 关于使用css制作三角符号,网上有很多的例子了,在这里只是为了详细的向各位解释一下三角符号的原理 下图,是一个长宽为100px,边框宽度为100px的一个元素,由此可见,在cs ...

  9. HTTP&HTTPS

    主要参考文档:<图解HTTP> HTTP简介 什么是HTTP? HTTP:(HyperText Transfer Protocol),超文本传输协议,是一个基于请求和响应,无状态的,应用层 ...

  10. Spring Boot 整合 Freemarker,50 多行配置是怎么省略掉的?

    Spring Boot2 系列教程接近完工,最近进入修修补补阶段.Freemarker 整合貌似还没和大家聊过,因此今天把这个补充上. 已经完工的 Spring Boot2 教程,大家可以参考这里: ...