Progressive web application development --- use indexedDB implement ajax local data store (D)

In several previous articles, we use a service worker optimized our page step by step, and now we learn to use our previous indexedDB, to cache our ajax request, first visit the page, we request ajax, when we continue time to refresh the page, we read from the cache to the json data, you want to know indexedDB, please see this article .
The following demo of our project is to build further on the basis of our third article of the above, would like to know before the article, please click here .

We still follow the idea before we do, let's first take a look at our entire project structure is as follows:

| ----- project
 | | --- public
 | | | --- JS # store all JS
 | | | | --- main.js # Entrance JS file
 | | | | --- store.js
 | | | | --- myAccount.js
 | | | --- style # store all CSS
 | | | | --- main.styl # entrance CSS file
 | | | --- json # local store analog data json file
 | | | | --- index.json 
 | | | --- index.html # index.html page
 | | | --- ImagesRF Royalty Free
 | | --- package.json
 | | --- webpack.config.js
 | | --- node_modules
 | | --- sw.js

public / js / index.json (if backend interface returns data following data) code is as follows:

{
  "code": 0,
  "data": [
    { "name": "kongzhi111", "age": 28},
    { "name": "kongzhi222", "age": 29},
    { "name": "kongzhi333", "age": 30}
  ]
}

Store.js create a new file in our public / js, the role of the js file is to use indexedDB our ajax request to cache data. And we need to store the file in our store.js sw.js in CACHE_URLS, as illustrated in the following example:

var CACHE_URLS = [
   "/public/index.html",       // HTML file 
  "/main.css",                // CSS style sheet 
  "/public/images/xxx.jpg",   // pictures 
  "/main.js",                  // JS file 
  "/public/js/store.js" 
];

Then we started to write our store.js codes, / public / js / store.js code is as follows:

Axios from Import 'Axios' ; 

var OpenDatabase = function () {
   IF (! window.indexedDB) {
     return  to false ; 
  } 
  // Open or create a store-data database 
  var Result = window.indexedDB.open ( 'store-data', 2 ); 

  // listener error function triggers 
  result.onerror = function (Event) { 
    the console.log ( "the DataBase error:" , event.target.error); 
  } 
  // monitor the current version number is upgraded function triggered when the 
  result = .onupgradeneeded function (Event) {
     var DB = event.target.result;
    / * 
     Contains the object repository name (or called table name). If you do not create one. 
     KeyPath object attribute id of the primary key 
    * / 
    IF (db.objectStoreNames.contains ( 'Store'! )) { 
      Db.createObjectStore ( "Store", {keyPath: "id", autoIncrement: to true }); 
    } 
  } 
  return Result; 
}; 
/ * 
 @param {} storeName warehouse or table names in 
 @param {successCallback} callback function to be executed 
 @param {transactionMode} readOnly transaction read-only mode, readwrite readable and writable 
* / 
var openObjectStore = function (storeName , successCallback, TransactionMode) {
   var DB = OpenDatabase ();
   IF (!DB) {
     return  to false ; 
  } 
  db.onsuccess = function (Event) {
     var targetValue = event.target.result;
     / *  
     1. Use targetValue.transaction (storeName, transactionMode) to create a transaction 
     2. After creating the transaction, we use targetValue .transaction (storeName, transactionMode) .objectStore ( storeName) 
     of this method, the object to get IDBObjectStore. 
    * / 
    Var objectStore = targetValue.transaction (storeName, TransactionMode) .objectStore (storeName); 
    successCallback (objectStore); 
  }; 
  return  to true ; 
}; 

var getStore = function(successCallback) {
   var DATAS = [];
   var DB = openObjectStore ( "Store", function (objectStore) {
     // use bids objectStore.openCursor () 
    . objectStore.openCursor () onSuccess = function (Event) {
       var Cursor = Event .target.result;
       // if the subject stream, then put the data into the array to go inside datas are sequentially stored into the circulation 
      IF (Cursor) { 
        datas.push (cursor.value); 
        . Cursor Continue (); 
      } the else {
         // otherwise, if there is data datas, then it supports the callback function 
        IF (datas.length> 0 ) {
          successCallback (datas); 
        } the else {
           // If datas data is empty, sending a request json 
          axios.get ( "HTTP: // localhost: 8081 / public / json / index.json") .then (datas => {
             var = List datas.data.data;
             // open the repository or table, perform transaction operations corresponding 
            openObjectStore ( "Store", function (datasStore) {
               for (the let I = 0; I <List.length; I ++ ) { 
                datasStore .add (List [I]); 
              } 
              successCallback (DATAS); 
            }, "ReadWrite" ); 
          }); 
        } 
      }
    }
  });
  if (!db) {
    axios.get("http://localhost:8081/public/json/index.json", successCallback);
  }
};

window.getStore = getStore;

As the code, there are three functions, respectively openDataBase, openObjectStore, and getStore, then the first function OpenDatabase () will open a new database request, the internal code function, first determines whether the browser supports window.indexedDB, if not support, direct return, and then we create a store-data database, and monitor the onerror, onupgradeneeded event, and finally we have created a store or warehouse name called table name. And in id as the primary key, and autoIncrement set to true, the automatic increase. Then we return the result. Because our onsuccess event and does not hear in this method. In the second function openObjectStore, we will call this function to create the database, and to listen onsuccess this event.
openObjectStore () This function opens a transaction on an object, its operation and function, the first parameter of the method is the name of the warehouse, the second parameter is a successful callback open warehouse, the third parameter is parameter that its meaning is the type of transaction, there readonly (read only) or ReadWrite (read-write), such as code:

= db.onsuccess function (Event) {
   var targetValue = event.target.result;
   / *  
   1. Use targetValue.transaction (storeName, transactionMode) to create a transaction 
   2. After creating the transaction, we use targetValue.transaction (storeName, transactionMode) .objectStore (storeName) 
   this method, get IDBObjectStore object. 
  * / 
  Var objectStore = targetValue.transaction (storeName, TransactionMode) .objectStore (storeName); 
  successCallback (objectStore); 
};

First, we use this code: use targetValue.transaction (storeName, transactionMode) to create a transaction, and then create after the transaction is completed, then we use

targetValue.transaction (storeName, transactionMode) .objectStore (
storeName); this method, the object to get IDBObjectStore. The object is then passed inside successCallback function, the callback function, we can use objectStore to increase the data.

getStore (): This function receives a successCallback parameters, refer to the callback function, the internal code, we will first create a transaction, the following code:

var db = openObjectStore("store", function(objectStore) {
  
}

Then we'll create bids, and iterate over all the data, and monitor onsuccess function, the following code:

var DB = openObjectStore ( "Store", function (objectStore) {
   // use bids objectStore.openCursor () 
  objectStore.openCursor () = onSuccess. function (Event) {
     var Cursor = event.target.result;
     // If there are bids then put the data into the array to go inside datas are sequentially stored into the circulation 
    IF (Cursor) { 
      datas.push (cursor.value); 
      . Cursor Continue (); 
    } the else {
       // otherwise, if the data words datas , to support call the callback function 
      IF (datas.length> 0 ) { 
        successCallback (DATAS); 
      } the else {
         //If datas data is empty, sending a request json 
        axios.get ( "HTTP: // localhost: 8081 / public / json / index.json") .then (datas => {
           var List = datas.data.data;
           // open data warehouse or table, perform transaction operations corresponding 
          openObjectStore ( "Store", function (datasStore) {
             for (the let I = 0; I <List.length; I ++ ) { 
              datasStore.add (List [I]); 
            } 
            successCallback (DATAS); 
          }, "ReadWrite" ); 
        }); 
      } 
    } 
  } 
}

Will be called when the above code, if there is flow target, then the bids each advance to a new record, even in the bids will be called after the last record by, it is to circulate a call to the internal through continue, when the last when a record, behind it there is no data, so it will enter the interior else statement. So it will first determine whether the datas data, if there is data, it would call successCallback (datas); this code, the data datas as a parameter passed back to successCallback callback function, otherwise, if the datas is empty, we will to request our local json request, send ajax request, then the requested data is stored in a warehouse to store name, followed by the cycle is complete, we then call successCallback method, the data datas to pass out as a parameter. Of course, in our third function getStore function, if not supported window.indexedDB, then the browser, we go directly to request ajax, such as the last sentence getStore Code:

if (!db) {
  axios.get("http://localhost:8081/public/json/index.json", successCallback);
}

Finally, our store.js, we will use window.getStore = getStore; make them global. Then our /public/js/myAccount.js code below, you can call our method getStore in the store.js, as shown in the following code:

from $ Import 'jQuery' ; 

$ ( function () {
   // request data and rendering data 
  requestAndRenderFunc (); 


  // request data to the server, and the page rendering 
  function requestAndRenderFunc () { 
    getStore (renderHTMLFunc); 
  }; 

  function renderHTMLFunc (DATAS ) { 
    the console.log (DATAS); 
  } 
});

As the code is optimized after all, indexedDB use to store our data. So let's test the next page, we have our browser cache data is first emptied, the next and then the first time we visit our page, we can see on our network, show the following request:

Then we will see the data returned in the console, as shown below:

As our first request, we can see will ask ajax, then will return the contents, and now we continue to refresh our page, you can see this request as follows:

Then we look at the console of printing are as follows:

我们可以看到我们ajax请求并没有发请求,但是我们依然可以拿到数据,这是为什么呢?这是因为我们使用 indexedDB缓存ajax数据到本地,因此当我们第二次以后请求的时候,我们拿的都是 indexedDB里面的数据,我们并没有发ajax请求,所以使用该访问,哪怕以后访问我们的页面,即使没有网络的情况下,我们依然可以拿到数据,并且更快加载我们的页面。我们再来看下我们的 indexedDB存储的数据如下所示:

如上代码我们已经实现了使用indexedDB对数据缓存了,并且使用 indexedDB缓存里面的数据了,但是现在有一个新的问题,并且用户点击一个查询按钮,但是查询按钮的条件发生改变了,因此ajax请求返回的数据也是根据页面中查询的条件来返回的,因此这个时候我们就不能一直使用 indexedDB中的数据了,我们需要重新请求页面的数据,因此我们需要在我们的 store.js 添加如下代码了:

var addToObjectStore = function(storeName, object) {
  openObjectStore(storeName, function(store) {
    store.add(object);
  }, "readwrite");
};

var updateInObjectStore = function(storeName, id, object) {
  openObjectStore(storeName, function(objectStore) {
    objectStore.openCursor().onsuccess = function(event) {
      var cursor = event.target.result;
      if (!cursor) {
        return;
      }
      if (cursor.value.id === id) {
        objectStore.put(object);
        return;
      }
      cursor.continue();
    }
  }, "readwrite");
}

window.addToObjectStore = addToObjectStore;
window.updateInObjectStore = updateInObjectStore;

如上 addToObjectStore 函数接收对象存储的名称以及要放进存储的新对象作为参数,该函数我们可以使用如下方式来进行调用:

addToObjectStore("store", { id: 1 });

第二个函数 updateInObjectStore 接收对象存储的名称,找到与给定的id参数匹配的id对象,并且用它来更新对象,这是通过在对象存储上打开 readwrite事务,并且使用流标进行迭代来完成的。在流标到达最后一条记录或匹配成功之前,函数会一直迭代。如果找到匹配项,就会通过 objectStore.put(object); 来进行更新,此时函数就会通过return返回回来,因为一旦找到匹配,就不需要继续迭代下一条记录了。该函数可以如下调用:

updateInObjectStore("store", 1, {"id": 1, name: 'kongzhi', age: 30 });

因此为了演示下,我们需要把我们的index.html 代码变成如下了:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>service worker 实列</title>
</head>
<body>
  <div id="app">222226666</div>
  <img src="/public/images/xxx.jpg" />
  <div style="cursor: pointer;color:red;font-size:18px;padding:5px;border:1px solid #333;" id="submit">点击我新增</div>

  <div style="cursor: pointer;color:red;font-size:18px;padding:5px;border:1px solid #333;" id="update">点击我修改</div>

</body>
</html>

如上代码,我们新增了 id = "submit" div元素,和 id = "update" 的元素,然后需要在我们的myAccount.js 代码添加如下:

function updateDisplay(d) {
  console.log(d);
};
function renderHTMLFunc(datas) {
  console.log(datas);
}
var addStore = function(id, name, age) {
  var obj = {
    id: id,
    name: name,
    age: age
  };
  addToObjectStore("store", obj);
  renderHTMLFunc(obj);
  $.getJSON("http://localhost:8081/public/json/index.json", obj, function(data) {
    updateDisplay(data);
  });
};
$("#submit").click(function(e) {
  addStore(3, 'longen1', '111');
});
$("#update").click(function(e) {
  $.getJSON("http://localhost:8081/public/json/index.json", {id: 1}, function(data) {
    updateInObjectStore("store", 1, data);
    updateDisplay(data);
  });
});

如上代码,当我们点击 id 为 submit的元素的时候,我们会调用 addStore 函数,在该函数内部会根据 id, name, age 参数来新增一条数据,然后会调用 addToObjectStore 函数,先把数据添加到本地存储里面去,然后在渲染页面 调用 renderHTMLFunc 函数,最后使用 $.getJSON 请求一条数据,然后把最新的数据渲染到页面上去。

同样的道理,update数据的时候,我们会发ajax请求,无论服务器端是否返回了新的数据,我们都会调用 updateInObjectStore 这个函数来更新我们本地的数据。这样就实现了,如果是状态发送改变的话,那么本地indexedDB存储的数据库也会重新得到更新。

我们可以在我们的项目点击下就可以看到效果了。我们点击新增一条数据后,在我们的 indexedDB中看到信息如下:

如上我们这边没有把 data里面的数据抽离出来,直接把一整个数据直接添加进去了,反正就是这个意思,新增的时候,重新能更新我们的indexedDB里面的数据,同理我们update修改数据的时候,我们也一样可以修改我们的某一条数据的。

github源码查看demo

Guess you like

Origin www.cnblogs.com/tugenhua0707/p/11222017.html