HTML5 Web 客户端五种离线存储方式汇总
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
最近折騰HTML5游戲需要離線存儲功能,便把目前可用的幾種HTML5存儲方式研究了下,基于HT for Web寫了個綜合的實例,分別利用了Cookie、WebStorage、IndexedDB以及FileSystem四種本地離線存儲方式,對燃氣監(jiān)控系統(tǒng)的表計位置、朝向、開關(guān)以及表值等信息做了CURD的存取操作。
HTML5的存儲還有一種Web SQL Database方式,雖然還有瀏覽器支持,是唯一的關(guān)系數(shù)據(jù)庫結(jié)構(gòu)的存儲,但W3C以及停止對其的維護和發(fā)展,所以這里我們也不再對其進行介紹: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數(shù)據(jù)模型信息進行序列化和反序列化,這個過程很簡單通過dataModel.serialize()將模型序列化成JSON字符串,通過dataModel.deserialize(jsonString)將JSON字符串內(nèi)存反序列化出模型信息,而存儲主要就是主要就是針對JSON字符串進行操作。
先介紹最簡單的存儲方式LocalStorage,代碼如下,幾乎不用介紹就是Key-Value的簡單鍵值對存儲結(jié)構(gòu),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,本例中我只能保存一個圖元的信息,這種存儲方式存儲內(nèi)容很有限,只適合做簡單信息存儲,存取接口設(shè)計得極其反人類,為了介紹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可以存儲結(jié)構(gòu)對象,可構(gòu)建key和index的索引方式查找,目前各瀏覽器的已經(jīng)逐漸支持IndexedDB的存儲方式,其使用代碼如下,需注意IndexedDB的很多操作接口類似NodeJS的異步回調(diào)方式,特別是查詢時連cursor的continue都是異步再次回調(diào)onsuccess函數(shù)的操作方式,因此和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相當(dāng)于操作本地文件的存儲方式,目前支持瀏覽器不多,其接口標準也在發(fā)展制定變化中,例如在我寫這個代碼時大部分文獻使用的webkitStorageInfo已被navigator.webkitPersistentStorage和navigator.webkitTemporaryStorage替代,存儲的文件可通過filesystem:http://www.hightopo.com/persistent/meters.txt’的URL方式在chrome瀏覽器中查找到,甚至可通過filesystem:http://www.hightopo.com/persistent/類似目錄的訪問,因此也可以動態(tài)生成圖片到本地文件,然后通過filesystem:http:***的URL方式直接賦值給img的html元素的src訪問,因此本地存儲打開了一扇新的門,相信以后會冒出更多稀奇古怪的奇葩應(yīng)用。
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的存儲方式還在快速的發(fā)展中,其實除了以上幾種外還有Application Cache,相信將來還會有新秀出現(xiàn),雖然“云”是大趨勢,但客戶端并非要走極端的“瘦”方案,這么多年冒出了這么多客戶端存儲方式,說明讓客戶端更強大的市場需求是強烈的,當(dāng)然目前動蕩階段苦逼的是客戶端程序員,除了要適配Mouse和Touch,還要適配各種屏,如今還得考慮適配各種存儲,希望本文能在大家選型客戶端存儲方案時有點幫助,最后上段基于HT for Web操作HTML5存儲示例的視頻效果:http://v.youku.com/v_show/id_XODUzODU2MTY0.html
轉(zhuǎn)載于:https://my.oschina.net/xhload3d/blog/359062
總結(jié)
以上是生活随笔為你收集整理的HTML5 Web 客户端五种离线存储方式汇总的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JSP复习笔记——第10章 连接数据库
- 下一篇: Windows+Git+Tortoise