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

Indexed Database

IndexedDB也是一种数据库的存储机制,但不同于已经不再支持的Web SQL Database。IndexedDB不是传统的关系数据库,可归为NoSQL数据库。IndexedDB又类似于Dom
Storage的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
、存储对象(可理解成表)以及表中添加的数据。

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的优点,用于存储大块或复杂结构的数据,提供更大的存储空间,使用起来也比较简单。可以作为Web
SQL 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>

本文文字及图片出自 CSDN

余下全文(1/3)
分享这篇文章:

请关注我们:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注