如何在同一事务中动态创建和填充HTML5 IndexedDB上的多个objectStore?

时间:2017-01-26 22:44:17

标签: javascript fetch indexeddb

使用 IndexedDB API ,当用户加载网页时,我在一个事务中创建属于同一数据库的许多objectStore。

我命令这样做,我创建了一个包含许多要创建的对象库的对象,每个对象都有它的名称,数据和索引。

然后一个函数运行该对象并有效地为每个对象创建Database,objectStores和索引。

然而,在所有OS的创建中,只填充了对象的最后一个成员。比如要创建和填充5个对象,创建5个,但只填充最后一个 显然,这是一个覆盖问题或与JS堆栈或异步性有关的问题。

我感谢任何帮助,使代码填充所有操作系统而不是最后一个操作系统 我的浏览器是Chrome 56,我从API中获取数据,其响应正常,而且我在vanillajs上编码。感谢您对vanillajs的帮助,没有办法使用任何与现代Web平台不同的库或框架。

以下是代码:

在HTML方面,这是对象的一个​​示例:

var datastores = [{osName:'items', osEndpoint: '/api/data/os/1/1', osIndex:'value'}, {osName:'categories', osEndpoint: '/api/data/os/2/1', osIndex: 'idc'}];

关于javascript:

 var request = indexedDB.open(DB_NAME, DB_VERSION); // open database.

 request.onerror = function (e) { // error callback
    console.error("error: " +  e.target.errorCode);
 };

 request.onupgradeneeded = function (e) { // the onupgradeneeded event which creates  all schema,  dataabase, objectstores and populates OS.
 var db = this.result; 

 for (var i in datastores) { // loop the objectStore object.
   var objectStore = db.createObjectStore(datastores[i].osName, {keyPath: "id"});

   TB_NAME = datastores[i].osName;  // instantiate each objectStore name.
   objectStore.createIndex(datastores[i].osIndex, datastores[i].osIndex,  { unique: false });  // create each index.

   objectStore.transaction.oncomplete = function(e) { // oncomplete event, after creating OS...
        fetchGet(datastores[i].osEndpoint, popTable);  // runs a function to fetch from a designated endpoint and calls a function.
    };
 }
}

现在的功能:获取数据和填充数据:

  function fetchGet(url, function) {  // fetch from API.
     fetch(url, {
        method: 'GET'
     }).then(function(response) {
         return response.json();
     }).then(function(json) {
         popTable (json);
     }).catch(function(err) {
        console.log('error!', err);
     });
   }


 function popTable(json) {
    var m = 0;
    var tx = db.transaction(TB_NAME, "readwrite");

    tx.oncomplete = function(e) {
        console.log("Completed Transaction " + TB_NAME);
    };

    tx.onerror = function(e) {
        console.error("error: " +  e.target.errorCode);
    };

    var txObjectStore = tx.objectStore(TB_NAME);
    for (m in json) {
        var request = txObjectStore.add(json[m]);
        request.onsuccess = function (e) {
        console.log('adding... ' );  
       }; 
    }
 }

1 个答案:

答案 0 :(得分:0)

for (var i in datastores)循环同步运行,每次都更新全局TB_NAME变量。循环结束后,TB_NAME将保留最后一个对象库的名称。

当异步popTable调用运行时,TB_NAME将永远保留最后一个商店的名称,因此这是唯一一个将更新的商店。尝试将日志记录添加到popTable以查看此内容。

您需要以某种方式传递商店名称的当前值(例如,作为fetchGet的参数)。另请注意,虽然在调用popTable时将fetchGet作为参数传递,但实际上并未将其作为参数接受。

...

具体变化:

更改您致电fetchGet以包含商店名称的方式:

fetchGet(datastores[i].osEndpoint, popTable, datastores[i].osName);

更改fetchGet功能以接受参数:

function fetchGet(url, func, name) {

然后不要直接调用popTable,而是执行:

     func(json, name);

然后将popTable的定义更改为:

function popTable(json, name) {

...并在交易中使用name