gpt4 book ai didi

safari - TransactionInactiveError : Failed to execute 'get' on 'IDBObjectStore' : The transaction is inactive or finished

转载 作者:行者123 更新时间:2023-12-03 20:30:03 28 4
gpt4 key购买 nike

这似乎是 Safari 唯一的错误。据我所知,它不会出现在 Chrome 中。我有一个非常标准的 IndexedDB 设置。我调用 initDb,保存结果,这为我提供了一种调用数据库的好方法。

var initDb = function() {
// Setup DB. whenDB is a promise we use before executing any DB requests so we know the DB is fully set up.
parentDb = null;
var whenDb = new Promise(function(resolve, reject) {
var DBOpenRequest = window.indexedDB.open('groceries');
DBOpenRequest.onsuccess = function(event) {
parentDb = DBOpenRequest.result;
resolve();
};
DBOpenRequest.onupgradeneeded = function(event) {
var localDb = event.target.result;
localDb.createObjectStore('unique', {
keyPath: 'id'
});
};
});

// makeRequest needs to return an IndexedDB Request object.
// This function just wraps that in a promise.
var request = function(makeRequest, key) {
return new Promise(function(resolve, reject) {
var request = makeRequest();
request.onerror = function() {
reject('Request error');
};
request.onsuccess = function() {
if (request.result == undefined) {
reject(key + ' not found');
} else {
resolve(request.result);
}
};
});
};

// Open a very typical transaction
var transact = function(type, storeName) {
// Make sure DB is set up, then open transaction
return whenDb.then(function() {
var transaction = parentDb.transaction([storeName], type);
transaction.oncomplete = function(event) {
console.log('transcomplete')
};
transaction.onerror = function(event) {
console.log('Transaction not opened due to error: ' + transaction.error);
};
return transaction.objectStore(storeName);
});
};

// Shortcut function to open transaction and return standard Javascript promise that waits for DB query to finish
var read = function(storeName, key) {
return transact('readonly', storeName).then(function(transactionStore) {
return request(function() {
return transactionStore.get(key);
}, key);
});
};

// A test function that combines the previous transaction, request and read functions into one.
var test = function() {
return whenDb.then(function() {
var transaction = parentDb.transaction(['unique'], 'readonly');
transaction.oncomplete = function(event) {
console.log('transcomplete')
};
transaction.onerror = function(event) {
console.log('Transaction not opened due to error: ' + transaction.error);
};
var store = transaction.objectStore('unique');
return new Promise(function(resolve, reject) {
var request = store.get('groceryList');
request.onerror = function() {
console.log(request.error);
reject('Request error');
};
request.onsuccess = function() {
if (request.result == undefined) {
reject(key + ' not found');
} else {
resolve(request.result);
}
};
});
});
};

// Return an object for db interactions
return {
read: read,
test: test
};
};
var db = initDb();

当我调用 db.read('unique', 'test')在 Safari 中我得到错误:
TransactionInactiveError: Failed to execute 'get' on 'IDBObjectStore': The transaction is inactive or finished

Chrome 中的相同调用没有错误,只是返回了预期的 promise 。奇怪的是,在 Safari 中调用 db.test 函数也可以正常工作。从字面上看,Safari 中将工作分为两个功能似乎导致了这个错误。

在所有情况下 transcomplete在抛出错误(在 Safari 错误的情况下)或返回正确的值(应该发生)之后记录。因此,在表示事务不活动或已完成的错误被抛出之前,事务还没有关闭。

很难在这里找到问题。

最佳答案

嗯,对我的回答没有信心,但我的第一个猜测是在创建事务和启动请求之间发生的暂停允许事务超时并变为非事件状态,因为它发现没有事件的请求,这样以后的请求确实会尝试开始在非事件事务上启动。这可以通过在 javascript 事件循环的同一时期(相同的滴答声)开始请求而不是推迟请求的开始来轻松解决。

错误最有可能出现在这些行中:

var store = transaction.objectStore('unique');
return new Promise(function(resolve, reject) {
var request = store.get('groceryList');

您需要立即创建请求以避免此错误:
var store = transaction.objectStore('unique');
var request = store.get('groceryList');

解决这个问题的一种方法可能是简单地以不同的方式处理代码。 Promise 旨在是可组合的。使用 Promise 的代码通常希望将控制权返回给调用者,以便调用者可以控制流程。您当前编写的某些功能违反了此设计模式。通过简单地使用更合适的设计模式,您可能不会遇到此错误,或者至少您将能够更容易地识别问题。

另外一点是您对全局变量的混合使用。像 parentDb 这样的变量和 db除非您真的是异步代码专家,否则可能会在某些平台上引起问题。

例如,从解析为打开的 IDBDatabase 变量的简单连接或打开函数开始。
function connect(name) {
return new Promise(function(resolve, reject) {
var openRequest = indexedDB.open(name);
openRequest.onsuccess = function() {
var db = openRequest.result;
resolve(db);
};
});
}

这将使您可以轻松地编写一个开放的 Promise 以及应该在它之后运行的代码,如下所示:
connect('groceries').then(function(db) {
// do stuff with db here
});

接下来,使用 Promise 封装操作。这不是每个请求的 promise 。传递 db 变量而不是使用全局变量。
function getGroceryList(db, listId) {
return new Promise(function(resolve, reject) {
var txn = db.transaction('unique');
var store = txn.objectStore('unique');
var request = store.get(listId);
request.onsuccess = function() {
var list = request.result;
resolve(list);
};
request.onerror = function() {
reject(request.error);
};
});
}

然后将它们组合在一起
connect().then(function(db) {
return getGroceryList(db, 'asdf');
}).catch(error);

关于safari - TransactionInactiveError : Failed to execute 'get' on 'IDBObjectStore' : The transaction is inactive or finished,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50849690/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com