some Good ideas前端

H5的离线存储方案

2019-01-31  本文已影响455人  grain先森

1. Web SQL Database

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.


Web SQL Database

整个示例主要就是将HT for Web的DataModel数据模型信息进行序列化和反序列化,这个过程很简单通过dataModel.serialize()将模型序列化成JSON字符串,通过dataModel.deserialize(jsonString)将JSON字符串内存反序列化出模型信息,而存储主要就是主要就是针对JSON字符串进行操作。


流程图

2. LocalStorage

先介绍最简单的存储方式LocalStorage,代码如下,几乎不用介绍就是Key-Value的简单键值对存储结构,Web Storage除了localStorage的持久性存储外,还有针对本次回话的sessionStorage方式,一般情况下localStorage较为常用。
这两种存储方式的API也一样,详细说明可以自行百度。
获取某一条:localStorage.getItem("key")、sessionStorage.getItem("key");
存储某一条:localStorage.setItem("key", value)、sessionStorage.setItem("key", value);
删除某一条:localStorage.removeItem("key")、sessionStorage.removeItem("key");
删除所有:localStorage.clear()、sessionStorage.clear();

localStorage和sessionStorage

3. Cookie

最古老的存储方式为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"; 
   }
}

4. Indexed Database API

如今比较实用强大的存储方式为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');
     } 
   };
}

5. FileSystem API

最后是FileSystem API相当于操作本地文件的存储方式,目前支持浏览器不多,其接口标准也在发展制定变化中,例如在我写这个代码时大部分文献使用的webkitStorageInfo已被navigator.webkitPersistentStorage和navigator.webkitTemporaryStorage替代,存储的文件可通过filesystem的URL方式在chrome浏览器中查找到,甚至可通过filesy类似目录的访问,因此也可以动态生成图片到本地文件,然后通过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');
     });
   }); 
}
FileSystem API

6. 其他

Browser-Side的存储方式还在快速的发展中,其实除了以上几种外还有Application Cache,相信将来还会有新秀出现,虽然“云”是大趋势,但客户端并非要走极端的“瘦”方案,这么多年冒出了这么多客户端存储方式,说明让客户端更强大的市场需求是强烈的,当然目前动荡阶段苦逼的是客户端程序员,除了要适配Mouse和Touch,还要适配各种屏,如今还得考虑适配各种存储,希望本文能在大家选型客户端存储方案时有点帮助。

关注公众号【grain先森】,回复关键词 【18福利】,获取为你准备的年终福利,更多关键词玩法期待你的探索~

上一篇下一篇

猜你喜欢

热点阅读