如何在同一事务中在 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
。
在 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
。