zoukankan      html  css  js  c++  java
  • 渐进式web应用开发---promise式数据库(五)

    在前面的一篇文章中,我们已经实现了使用indexedDB实现ajax本地数据存储的功能,详情,请看这篇文章。现在我们需要把上面的一篇文章中的代码使用promise结构来重构下。我们为什么需要使用promise来重构呢?我们之前一直使用 indexedDB中的代码,但是在indexedDB中,我们代码很大程度上依赖于回调,如果我们的代码越来越多,我们需要的回调嵌套就越来越多,这对于后期代码维护不是很好。

    比如我们可以看看我们之前的代码如下所示:

    // 打开或创建 store-data 数据库
    var result = window.indexedDB.open('store-data', 3);
    
    // 监听error函数触发
    result.onerror = function(event) {
      console.log("DataBase error:", event.target.error);
    }
    // 监听当前版本号被升级的时候触发该函数
    result.onupgradeneeded = function(event) {
      var db = event.target.result;
      /*
       是否包含该对象仓库名(或叫表名)。如果不包含就创建一个。
       该对象中的 keyPath属性id为主键
      */
      if (!db.objectStoreNames.contains('store')) {
        db.createObjectStore("store", { keyPath: "id", autoIncrement: true });
      }
    }
    
    result.onsuccess = function(event) {
      var targetValue = event.target.result;
      /* 
       1. 使用 targetValue.transaction(storeName, transactionMode) 来创建事务
       2. 创建事务之后,我们使用 targetValue.transaction(storeName, transactionMode).objectStore(storeName)
       这个方法,拿到 IDBObjectStore对象。
      */
      var objectStore = targetValue.transaction(storeName, transactionMode).objectStore(storeName);
      var request = objectStore.add({id: 3, name: 'kongzhi12', age: 31});
      request.onsuccess = function(event) {
        console.log('回调函数成功');
      }
      request.onerror = function(event) {
        console.log("DataBase error:", event.target.error);
      }
    }

    如上代码,我们打开了或创建了一个 store-data 数据库,然后把onsuccess回调附加到该请求上,在该onsuccess请求上,我们又有请求事件,接着有 onsuccess 回调函数,依次类推,如果以后代码越来越复杂的时候,我们以后代码就一直变成回调嵌套中,因此我们现在想使用promise方法来重构上面的代码,我们想要让上面的代码变成如下所示这样的:

    openDatabase('store-data', 3).then(function(db) {
      return openObjectStore(db, "store", "readwrite");
    }).then(function(objectStore){
      return addObject(objectStore, {"id": 3, "name": 'kongzhi123', 'age': 31});
    }).then(function(){
      console.log('回调成功');
    }).catch(function(error) {
      console.log('DataBase error', error);
    });

    我们希望变成如上的promise代码,我们希望将javascript异步回调的代码变成我们的promise代码。在重构我们的代码之前,我们先来看看我们的 XMLHttpRequest 代码,我们希望使用promise来重构该代码,在重构之前,我们先来看看XMLHttpRequest代码如下:

    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
      // 处理响应
    };
    xhr.onerror = function() {
      // 处理错误
    };
    xhr.open("get", '/xxx.json', true);
    xhr.send();

    如上这样的代码,是我们之前的xmlHttpRequest代码,现在我们可以使用我们的promise来重构我们上面的代码,因此重构后的代码变成如下所示:

    var promise_XHR = function(url, method) {
      return new Promise(function(resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.onload = resolve;
        xhr.onerror = reject;
        xhr.open(method, url, true);
        xhr.send();
      });
    };

    如上 promise_XHR 函数,该函数接收一个url 和 method参数,并返回了一个promise对象,该promise传入了一个函数,该函数有两个参数,代表成功和失败的回调,然后内部代码,我们创建了一个XMLHttpRequest对象,然后该对象 onload 函数的时候 把resolve 成功回调赋值给他,然后 xhr.onerror 函数的时候,把 reject 拒绝函数传递给他,我们调用方式如下所示:

    promise_XHR('/xxx.json', 'get').then(function(){
      // 处理成功的回调函数
    }).catch(error) {
      // 处理我们异常的回调函数
    }

    现在我们想把该方式使用到我们的 store.js 代码内部来。重构后的代码就变成了如下:

    import axios from 'axios';
    
    var DB_VERSION = 1;
    var DB_NAME = 'store-data2';
    
    var openDataBase = function() {
      return new Promise(function(resolve, reject) {
        if (!window.indexedDB) {
          reject("indexedDB not supported");
        }
        // 打开或创建 store-data 数据库
        var result = window.indexedDB.open(DB_NAME, DB_VERSION);
    
        // 监听error函数触发
        result.onerror = function(event) {
          console.log("DataBase error:", event.target.error);
        }
        // 监听当前版本号被升级的时候触发该函数
        result.onupgradeneeded = function(event) {
          var db = event.target.result;
          /*
           是否包含该对象仓库名(或叫表名)。如果不包含就创建一个。
           该对象中的 keyPath属性id为主键
          */
          if (!db.objectStoreNames.contains('store')) {
            db.createObjectStore("store", { keyPath: "id", autoIncrement: true });
          }
        }
        result.onsuccess = function(event) {
          resolve(event.target.result);
        }
      });
    };
    /*
     @param {storeName} 仓库名或表名
     @param {transactionMode} 事务模式 readOnly 只读,readwrite 可读可写
    */
    var openObjectStore = function(db, storeName, transactionMode) {
      return db.transaction(storeName, transactionMode).objectStore(storeName);
    };
    
    var getStore = function (successCallback) {
    
      return new Promise(function(resolve, reject) {
        openDataBase().then(function(db) {
          var objectStore = openObjectStore(db, 'store');
          var datas = [];
          objectStore.openCursor().onsuccess = function(event) {
            var cursor = event.target.result;
            if (cursor) {
              datas.push(cursor.value);
              cursor.continue();
            } else {
              if (datas.length > 0) {
                resolve(datas);
              } else {
                getDataFromServer().then(function(d) {
                  openDataBase().then(function(db) {
                    var objectStore = openObjectStore(db, "store", "readwrite");
                    for (let i = 0; i < datas.length; i++) {
                      objectStore.add(datas[i]);
                    }
                    resolve(datas);
                  });
                });
              }
            }
          }
        }).catch(function() {
          getDataFromServer().then(function(datas) {
            resolve(datas);
          });
        });
      });
    };
    
    function getDataFromServer() {
      return new Promise(function(resolve, reject) {
        axios.get("http://localhost:8081/public/json/index.json", resolve);
      });
    }
    
    var addToObjectStore = function(storeName, object) {
      return new Promise(function(resolve, reject) {
        openDataBase().then(function(db) {
          openObjectStore(db, storeName, 'readwrite').add(object).onsuccess = resolve;
        }).catch(function(error) {
          reject(error);
        })
      });
    };
    
    var updateInObjectStore = function(storeName, id, object) {
      return new Promise(function(resolve, reject) {
        openDataBase().then(function(db) {
          openObjectStore(db, storeName, "readwrite").openCursor().onsuccess = function(event) {
            var cursor = event.target.result;
            if (!cursor) {
              reject("store-data not found");
            }
            if (cursor.value.id === id) {
              cursor.put(object).onsuccess = resolve;
              return;
            }
            cursor.continue();
          }
        }).catch(function(){
          reject(error);
        })
      });
    }
    
    window.openDataBase = openDataBase;
    window.openObjectStore = openObjectStore;
    
    window.addToObjectStore = addToObjectStore;
    window.updateInObjectStore = updateInObjectStore;
    
    window.getStore = getStore;

    然后我们需要在我们的 myAccount.js 代码改成如下初始化所示:

    import $ from 'jquery';
    
    $(function() {
      openDataBase("store-data2", 2).then(function(db) {
        return openObjectStore(db, "store", "readwrite");
      }).then(function(objectStore) {
        return addToObjectStore("store", {id: 1, name: 'kongzhi111', age: 11});
      }).then(function() {
        console.log('添加成功');
      }).catch(function(error) {
        console.log("数据库加载失败", error);
      });
      /*
      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);
        });
      });
      */
    });

    然后会向我们的数据库中插入一条数据,我们刷新页面后查看我们的本地数据库如下所示:

     

    github源码demo查看

  • 相关阅读:
    Jmeter 指令记录
    做100个用户的并发测试时是不是得要100个用户的账号呀?
    以后可能会遇到的问题记录 .send_keys 无法输入的情况
    Appscan安装问题记录 + 最后问题解决的方法 和安装步骤
    fiddler工具能干啥
    Appscan_web安全测试工具 (含修改启动浏览器的方法)
    解决需要断言多个,其中有断言错误还要继续往下断言其他的方法
    (unittest之装饰器(@classmethod)) 让多个测试用例在一个浏览器里面跑 的方法
    unittest笔记
    另外一种结尾展示方法
  • 原文地址:https://www.cnblogs.com/tugenhua0707/p/11223556.html
Copyright © 2011-2022 走看看