HTML5 Web 客户端五种离线存储方式汇总
最近折腾HTML5游戏需要离线存储功能,便把目前可用的几种HTML5存储方式研究了下,基于HT for Web写了个综合的实例,分别利用了Cookie、WebStorage、IndexedDB以及FileSystem四种本地离线存储方式,对燃气监控系统的表计位置、朝向、开关以及表值等信息做了CURD的存取操作。
HTML5的存储还有一种Web SQL Database方式,虽然还有浏览器支持,是唯一的关系数据库结构的存储,但W3C以及停止对其的维护和发展,所以这里我们也不再对其进行介绍:Beware. This specification is no longer in active maintenance and the Web Applications Working Group does not intend to maintain it further.

整个示例主要就是将HT for Web的DataModel数据模型信息进行序列化和反序列化,这个过程很简单通过dataModel.serialize()将模型序列化成JSON字符串,通过dataModel.deserialize(jsonString)将JSON字符串内存反序列化出模型信息,而存储主要就是主要就是针对JSON字符串进行操作。
先介绍最简单的存储方式LocalStorage,代码如下,几乎不用介绍就是Key-Value的简单键值对存储结构,Web Storage除了localStorage的持久性存储外,还有针对本次回话的sessionStorage方式,一般情况下localStorage较为常用,更多可参考 http://www.w3.org/TR/webstorage/
function save(dataModel){
var value = dataModel.serialize();
window.localStorage['DataModel'] = value;
window.localStorage['DataCount'] = dataModel.size();
console.log(dataModel.size() + ' datas are saved');
return value;
}
function restore(dataModel){
var value = window.localStorage['DataModel'];
if(value){
dataModel.deserialize(value);
console.log(window.localStorage['DataCount'] + ' datas are restored');
return value;
}
return '';
}
function clear(){
if(window.localStorage['DataModel']){
console.log(window.localStorage['DataCount'] + ' datas are cleared');
delete window.localStorage['DataModel'];
delete window.localStorage['DataCount'];
}
}
最古老的存储方式为Cookie,本例中我只能保存一个图元的信息,这种存储方式存储内容很有限,只适合做简单信息存储,存取接口设计得极其反人类,为了介绍HTML5存储方案的完整性我顺便把他给列上:
function getCookieValue(name) {
if (document.cookie.length > 0) {
var start = document.cookie.indexOf(name + "=");
if (start !== -1) {
start = start + name.length + 1;
var end = document.cookie.indexOf(";", start);
if (end === -1){
end = document.cookie.length;
}
return unescape(document.cookie.substring(start, end));
}
}
return '';
}
function save(dataModel) {
var value = dataModel.serialize();
document.cookie = 'DataModel=' + escape(value);
document.cookie = 'DataCount=' + dataModel.size();
console.log(dataModel.size() + ' datas are saved');
return value;
}
function restore(dataModel){
var value = getCookieValue('DataModel');
if(value){
dataModel.deserialize(value);
console.log(getCookieValue('DataCount') + ' datas are restored');
return value;
}
return '';
}
function clear() {
if(getCookieValue('DataModel')){
console.log(getCookieValue('DataCount') + ' datas are cleared');
document.cookie = "DataModel=; expires=Thu, 01 Jan 1970 00:00:00 UTC";
document.cookie = "DataCount=; expires=Thu, 01 Jan 1970 00:00:00 UTC";
}
}
如今比较实用强大的存储方式为Indexed Database API,IndexedDB可以存储结构对象,可构建key和index的索引方式查找,目前各浏览器的已经逐渐支持IndexedDB的存储方式,其使用代码如下,需注意IndexedDB的很多操作接口类似NodeJS的异步回调方式,特别是查询时连cursor的continue都是异步再次回调onsuccess函数的操作方式,因此和NodeJS一样使用上不如同步的代码容易。
request = indexedDB.open("DataModel");
request.onupgradeneeded = function() {
db = request.result;
var store = db.createObjectStore("meters", {keyPath: "id"});
store.createIndex("by_tag", "tag", {unique: true});
store.createIndex("by_name", "name");
};
request.onsuccess = function() {
db = request.result;
};
function save(dataModel){
var tx = db.transaction("meters", "readwrite");
var store = tx.objectStore("meters");
dataModel.each(function(data){
store.put({
id: data.getId(),
tag: data.getTag(),
name: data.getName(),
meterValue: data.a('meter.value'),
meterAngle: data.a('meter.angle'),
p3: data.p3(),
r3: data.r3(),
s3: data.s3()
});
});
tx.oncomplete = function() {
console.log(dataModel.size() + ' datas are saved');
};
return dataModel.serialize();
}
function restore(dataModel){
var tx = db.transaction("meters", "readonly");
var store = tx.objectStore("meters");
var req = store.openCursor();
var nodes = [];
req.onsuccess = function() {
var res = req.result;
if(res){
var value = res.value;
var node = createNode();
node.setId(value.id);
node.setTag(value.tag);
node.setName(value.name);
node.a({
'meter.value': value.meterValue,
'meter.angle': value.meterAngle
});
node.p3(value.p3);
node.r3(value.r3);
node.s3(value.s3);
nodes.push(node);
res.continue();
}else{
if(nodes.length){
dataModel.clear();
nodes.forEach(function(node){
dataModel.add(node);
});
console.log(dataModel.size() + ' datas are restored');
}
}
};
return '';
}
function clear(){
var tx = db.transaction("meters", "readwrite");
var store = tx.objectStore("meters");
var req = store.openCursor();
var count = 0;
req.onsuccess = function(event) {
var res = event.target.result;
if(res){
store.delete(res.value.id);
res.continue();
count++;
}else{
console.log(count + ' datas are cleared');
}
};
}
最后是FileSystem API相当于操作本地文件的存储方式,目前支持浏览器不多,其接口标准也在发展制定变化中,例如在我写这个代码时大部分文献使用的webkitStorageInfo已被navigator.webkitPersistentStorage和navigator.webkitTemporaryStorage替代,存储的文件可通过filesystem:http://www.hightopo.com/persistent/meters.txt’的URL方式在chrome浏览器中查找到,甚至可通过filesystem:http://www.hightopo.com/persistent/类似目录的访问,因此也可以动态生成图片到本地文件,然后通过filesystem:http:***的URL方式直接赋值给img的html元素的src访问,因此本地存储打开了一扇新的门,相信以后会冒出更多稀奇古怪的奇葩应用。
navigator.webkitPersistentStorage.queryUsageAndQuota(function (usage, quota) {
console.log('PERSISTENT: ' + usage + '/' + quota + ' - ' + usage / quota + '%');
}
);
navigator.webkitPersistentStorage.requestQuota(2 * 1024 * 1024,
function (grantedBytes) {
window.webkitRequestFileSystem(window.PERSISTENT, grantedBytes,
function (fs) {
window.fs = fs;
});
}
);
function save(dataModel) {
var value = dataModel.serialize();
fs.root.getFile('meters.txt', {create: true}, function (fileEntry) {
console.log(fileEntry.toURL());
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function () {
console.log(dataModel.size() + ' datas are saved');
};
var blob = new Blob([value], {type: 'text/plain'});
fileWriter.write(blob);
});
});
return value;
}
function restore(dataModel) {
fs.root.getFile('meters.txt', {}, function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function (e) {
dataModel.clear();
dataModel.deserialize(reader.result);
console.log(dataModel.size() + ' datas are restored');
};
reader.readAsText(file);
});
});
return '';
}
function clear() {
fs.root.getFile('meters.txt', {create: false}, function(fileEntry) {
fileEntry.remove(function() {
console.log(fileEntry.toURL() + ' is removed');
});
});
}

Browser-Side的存储方式还在快速的发展中,其实除了以上几种外还有Application Cache,相信将来还会有新秀出现,虽然“云”是大趋势,但客户端并非要走极端的“瘦”方案,这么多年冒出了这么多客户端存储方式,说明让客户端更强大的市场需求是强烈的,当然目前动荡阶段苦逼的是客户端程序员,除了要适配Mouse和Touch,还要适配各种屏,如今还得考虑适配各种存储,希望本文能在大家选型客户端存储方案时有点帮助,最后上段基于HT for Web操作HTML5存储示例的视频效果:http://v.youku.com/v_show/id_XODUzODU2MTY0.html
HTML5 Web 客户端五种离线存储方式汇总的更多相关文章
- Android五种数据存储方式
android 五种数据存储 :SharePreferences.SQLite.Contert Provider.File.网络存储 Android系统提供了四种存储数据方式.分别为:SharePre ...
- [ Android 五种数据存储方式之四 ] —— ContentProvider存储数据
Android这个系统和其他的操作系统还不太一样,我们需要记住的是,数据在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据.那这个时候有读者就会提出问题,难道两个 ...
- Android中常用的五种数据存储方式
第一种: 使用SharedPreferences存储数据 适用范围: 保存少量的数据,且这些数据的格式非常简单:字符串型.基本类型的值.比如应用程序的各种配置信息(如是否打开音效.是否使用震动效果.小 ...
- [ Android 五种数据存储方式之三 ] —— SQLite存储数据
SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能.此外它还是开源的,任何人都可以使用它.许多开源项目((Mozilla, PHP, Python)都使用了 ...
- [ Android 五种数据存储方式之一 ] —— SharedPreferences存储数据
SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数. 主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceS ...
- [ Android 五种数据存储方式之二 ] —— 文件存储数据
关于文件存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的. 文件可用来存放大量数据,如文本.图片.音 ...
- Android系统的五种数据存储形式(二)
之前介绍了Android系统下三种数据存储形式,今天补充介绍另外两种,分别是内容提供者和网络存储.有些人可能认为内存提供者和网络存储更偏向于对数据的操作而不是数据的存储,但这两种方式确实与数据有关,所 ...
- Android系统的五种数据存储形式(一)
Android系统有五种数据存储形式,分别是文件存储.SP存储.数据库存储.contentprovider 内容提供者.网络存储.其中,前四个是本地存储.存储的类型包括简单文本.窗口状态存储.音频视频 ...
- Android编程中的5种数据存储方式
Android编程中的5种数据存储方式 作者:牛奶.不加糖 字体:[增加 减小] 类型:转载 时间:2015-12-03我要评论 这篇文章主要介绍了Android编程中的5种数据存储方式,结合实例形式 ...
随机推荐
- Vs2013 头文件注释
在vs2013的默认安装目录 1.CS类修改方式 在C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTempla ...
- MySql Windws 下自动备份脚本
这几天正在做一个 使用MySQL数据库的项目,目前项目已经完成了,当部署好项目之后,正在考虑如何自动备份MySql数据库的问题,我在网上找了一下资料终于解决了,特此记录一下. @echo off e ...
- 【腾讯Bugly干货分享】深入理解 ButterKnife,让你的程序学会写代码
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/578753c0c9da73584b025875 0.引子 话说我们做程序员的,都 ...
- nginx(2、反向代理)
反向代理是nginx最重要的特性之一,与正向代理相反,它代理的不是客户端,而是目标源,即我代理目标源满足客户端给出的请求. 在nginx中反向代理的简单配置如下: server { listen 80 ...
- Java IO8:IO简单总结
字节流.字符流继承关系 前几篇文章讲解了字节流.字符流的使用,不过Java提供给用户的流类远不止此,限于篇幅原因,没办法一一讲解,而且也没有必要一一讲解,就像我在写博客的时候多次提到的,有问题的时候学 ...
- 代码规范、代码复审、PSP
作业三: 代码规范.代码复审.PSP 代码规范 代码规范的重要性 一.规范的代码可以促进团队合作 一个项目大多都是由一个团队来完成,如果没有统一的代码规范,那么每个人的代码必定会风格迥异.且不说会存 ...
- js作用域问题一步步透彻理解
黄金守则第一条: js没有块级作用域(你可以自己闭包或其他方法实现),只有函数级作用域,函数外面的变量函数里面可以找到,函数里面的变量外面找不到. first try: 这是为什么呢?? var a ...
- 远程调试Java程序
java 可以以调试模式启动,启动后可以使用 jdb 对程序进行调试.以调试模式启动,需要加入以下参数: java -Xdebug -Xrunjdwp:transport=dt_socket,addr ...
- [蓝牙] 3、 剖析BLE心率检测工程
位于:<KEIL path> \ARM\Device\Nordic\nrf51822\Board\pca10001\s110\ble_app_hrs Heart Rate Example ...
- AngularJS快速入门指南13:表单
一个AngularJS表单是一组输入型控件的集合. HTML控件 HTML输入型标签标包括: input标签 select标签 button标签 textarea标签 HTML表单 HTML表单将各种 ...