转载

HTML5缓存机制浅析:移动端Web加载性能优化

Indexed Database

IndexedDB也是一种数据库的存储机制,但不同于已经不再支持的Web SQL Database。IndexedDB不是传统的关系数据库,可归为NoSQL数据库。IndexedDB又类似于DomStorage的key-value的存储方式,但功能更强大,且存储空间更大。

IndexedDB存储数据是key-value的形式。Key是必需,且要唯一;Key可以自己定义,也可由系统自动生成。Value也是必需的,但Value非常灵活,可以是任何类型的对象。一般Value都是通过Key来存取的。

IndexedDB提供了一组API,可以进行数据存、取以及遍历。这些API都是异步的,操作的结果都是在回调中返回。

下面代码演示了IndexedDB中DB的打开(创建)、存储对象(可理解成有关系数据的“表”)的创建及数据存取、遍历基本功能。

<script type="text/javascript"> var db; window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; //浏览器是否支持IndexedDB if (window.indexedDB) {    //打开数据库,如果没有,则创建    var openRequest = window.indexedDB.open("people_db", 1);    //DB版本设置或升级时回调    openRequest.onupgradeneeded = function(e) {        console.log("Upgrading...");        var thisDB = e.target.result;        if(!thisDB.objectStoreNames.contains("people")) {            console.log("Create Object Store: people.");            //创建存储对象,类似于关系数据库的表            thisDB.createObjectStore("people", { autoIncrement:true });           //创建存储对象, 还创建索引           //var objectStore = thisDB.createObjectStore("people",{ autoIncrement:true });          // //first arg is name of index, second is the path (col);         //objectStore.createIndex("name","name", {unique:false});        //objectStore.createIndex("email","email", {unique:true});      } } //DB成功打开回调 openRequest.onsuccess = function(e) {     console.log("Success!");     //保存全局的数据库对象,后面会用到     db = e.target.result;    //绑定按钮点击事件     document.querySelector("#addButton").addEventListener("click", addPerson, false);     document.querySelector("#getButton").addEventListener("click", getPerson, false);     document.querySelector("#getAllButton").addEventListener("click", getPeople, false);     document.querySelector("#getByName").addEventListener("click", getPeopleByNameIndex1, false); }   //DB打开失败回调   openRequest.onerror = function(e) {       console.log("Error");       console.dir(e);    } }else{     alert('Sorry! Your browser doesn't support the IndexedDB.'); } //添加一条记录 function addPerson(e) {     var name = document.querySelector("#name").value;     var email = document.querySelector("#email").value;     console.log("About to add "+name+"/"+email);     var transaction = db.transaction(["people"],"readwrite"); var store = transaction.objectStore("people");    //Define a person    var person = {        name:name,        email:email,        created:new Date()    }    //Perform the add    var request = store.add(person);    //var request = store.put(person, 2);    request.onerror = function(e) {        console.log("Error",e.target.error.name);        //some type of error handler    }    request.onsuccess = function(e) {       console.log("Woot! Did it.");    } } //通过KEY查询记录 function getPerson(e) {     var key = document.querySelector("#key").value;     if(key === "" || isNaN(key)) return;     var transaction = db.transaction(["people"],"readonly");     var store = transaction.objectStore("people");     var request = store.get(Number(key));     request.onsuccess = function(e) {         var result = e.target.result;         console.dir(result);         if(result) {            var s = "<p><h2>Key "+key+"</h2></p>";            for(var field in result) {                s+= field+"="+result[field]+"<br/>";            }            document.querySelector("#status").innerHTML = s;          } else {             document.querySelector("#status").innerHTML = "<h2>No match!</h2>";          }      } } //获取所有记录 function getPeople(e) {     var s = "";      db.transaction(["people"], "readonly").objectStore("people").openCursor().onsuccess = function(e) {         var cursor = e.target.result;         if(cursor) {             s += "<p><h2>Key "+cursor.key+"</h2></p>";             for(var field in cursor.value) {                 s+= field+"="+cursor.value[field]+"<br/>";             }             s+="</p>";             cursor.continue();          }          document.querySelector("#status2").innerHTML = s;      } } //通过索引查询记录 function getPeopleByNameIndex(e) {     var name = document.querySelector("#name1").value;     var transaction = db.transaction(["people"],"readonly");     var store = transaction.objectStore("people");     var index = store.index("name");     //name is some value     var request = index.get(name);     request.onsuccess = function(e) {        var result = e.target.result;        if(result) {            var s = "<p><h2>Name "+name+"</h2><p>";            for(var field in result) {                s+= field+"="+result[field]+"<br/>";            }            s+="</p>";     } else {         document.querySelector("#status3").innerHTML = "<h2>No match!</h2>";      }    } } //通过索引查询记录 function getPeopleByNameIndex1(e) {     var s = "";     var name = document.querySelector("#name1").value;     var transaction = db.transaction(["people"],"readonly");     var store = transaction.objectStore("people");     var index = store.index("name");     //name is some value     index.openCursor().onsuccess = function(e) {         var cursor = e.target.result;         if(cursor) {             s += "<p><h2>Key "+cursor.key+"</h2></p>";             for(var field in cursor.value) {                 s+= field+"="+cursor.value[field]+"<br/>";             }             s+="</p>";             cursor.continue();          }          document.querySelector("#status3").innerHTML = s;      } } </script> <p>添加数据<br/> <input type="text" id="name" placeholder="Name"><br/> <input type="email" id="email" placeholder="Email"><br/> <button id="addButton">Add Data</button> </p> <p>根据Key查询数据<br/> <input type="text" id="key" placeholder="Key"><br/> <button id="getButton">Get Data</button> </p> <div id="status" name="status"></div> <p>获取所有数据<br/> <button id="getAllButton">Get EveryOne</button> </p> <div id="status2" name="status2"></div> <p>根据索引:Name查询数据<br/>     <input type="text" id="name1" placeholder="Name"><br/>     <button id="getByName">Get ByName</button> </p> <div id="status3" name="status3"></div><br>

将上面的代码复制到indexed_db.html中,用Google Chrome浏览器打开,就可以添加、查询数据。在Chrome的开发者工具中,能查看创建的DB、存储对象(可理解成表)以及表中添加的数据。

HTML5缓存机制浅析:移动端Web加载性能优化

IndexedDB有个非常强大的功能,就是index(索引)。它可对Value对象中任何属性生成索引,然后可以基于索引进行Value对象的快速查询。

要生成索引或支持索引查询数据,需求在首次生成存储对象时,调用接口生成属性的索引。可以同时对对象的多个不同属性创建索引。如下面代码就对name和email两个属性都生成了索引。

var objectStore = thisDB.createObjectStore("people",{ autoIncrement:true }); //first arg is name of index, second is the path (col); objectStore.createIndex("name","name", {unique:false}); objectStore.createIndex("email","email", {unique:true});<br>

生成索引后,就可以基于索引进行数据的查询。

function getPeopleByNameIndex(e) { var name = document.querySelector("#name1").value; var transaction = db.transaction(["people"],"readonly"); var store = transaction.objectStore("people"); var index = store.index("name"); //name is some value var request = index.get(name); request.onsuccess = function(e) {     var result = e.target.result;     if(result) {         var s = "<p><h2>Name "+name+"</h2><p>";         for(var field in result) {             s+= field+"="+result[field]+"<br/>";         }         s+="</p>";     } else {         document.querySelector("#status3").innerHTML = "<h2>No match!</h2>";     }   } }<br>

分析:IndexedDB是一种灵活且功能强大的数据存储机制,它集合了Dom Storage和Web SQL Database的优点,用于存储大块或复杂结构的数据,提供更大的存储空间,使用起来也比较简单。可以作为WebSQL Database的替代。不太适合静态文件的缓存。

  1. 以key-value 的方式存取对象,可以是任何类型值或对象,包括二进制。
  2. 可以对对象任何属性生成索引,方便查询。
  3. 较大的存储空间,默认推荐250MB(分Host),比Dom Storage的5MB要大得多。
  4. 通过数据库的事务(tranction)机制进行数据操作,保证数据一致性。
  5. 异步的 API 调用,避免造成等待而影响体验。

Android在4.4开始加入对IndexedDB的支持,只需打开允许JS执行的开关就好了。

WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);<br>
正文到此结束
Loading...