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

How to dynamically create and populate multiple objectStores on HTML5 IndexedDB in the same transaction?

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

我为了这样做,创建了一个对象,其中包含许多要创建的 objectStores,每个都有它的名称、数据和索引。

然后一个函数运行该对象并有效地为每个对象创建数据库、对象存储和索引。

然而,在创建的所有 OS 中,只有对象的最后一个成员被填充。假设要创建和填充 5 个对象,创建了 5 个,但只填充了最后一个。
很明显是覆盖问题或者是JS栈或者异步相关的问题

感谢任何帮助使代码填充所有 OS 而不是最后一个。
我的浏览器是 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... ' );  
       }; 
    }
 }

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

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

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

...

具体变化:

更改调用 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