我正在做一个chrome扩展,它允许用户在YouTube视频上做笔记。笔记是使用IndexedDB存储的。我遇到了一个问题,如果我切换到另一个标签页,然后又切换回来,一个承诺返回undefined。首先,我使用的大部分代码使这个问题更容易理解。
// background.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if(request.message === 'get_notes') {
let getNotes_request = get_records(request.payload)
getNotes_request.then(res => { // This is where the error occurs, so the above function returns undefined
chrome.runtime.sendMessage({
message: 'getNotes_success',
payload: res
})
})
}
});
function create_database() {
const request = self.indexedDB.open('MyTestDB');
request.onerror = function(event) {
console.log("Problem opening DB.");
}
request.onupgradeneeded = function(event) {
db = event.target.result;
let objectStore = db.createObjectStore('notes', {
keypath: "id", autoIncrement: true
});
objectStore.createIndex("videoID, videoTime", ["videoID", "videoTime"], {unique: false});
objectStore.transaction.oncomplete = function(event) {
console.log("ObjectStore Created.");
}
}
request.onsuccess = function(event) {
db = event.target.result;
console.log("DB Opened.")
// Functions to carry out if successfully opened:
// insert_records(notes); This is only done when for the first run, so I will have some notes to use for checking and debugging. The notes are in the form of an array.
}
}
function get_records(vidID) {
if(db) {
const get_transaction = db.transaction("notes", "readonly");
const objectStore = get_transaction.objectStore("notes");
const myIndex = objectStore.index("videoID, videoTime");
console.log("Pre-promise reached!");
return new Promise((resolve, reject) => {
get_transaction.oncomplete = function() {
console.log("All Get Transactions Complete!");
}
get_transaction.onerror = function() {
console.log("Problem Getting Notes!");
}
let request = myIndex.getAll(IDBKeyRange.bound([vidID], [vidID, []]));
request.onsuccess = function(event) {
console.log(event.target.result);
resolve(event.target.result);
}
});
}
}
create_database();
现在来看看popup.js代码:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === 'getNotes_success') {
notesTable.innerHTML = ""; // Clear the table body
if (request.payload) {
// Code to display the notes.
} else {
// Display a message to add notes or refresh the table.
}
}
}
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
site = tabs[0].url; // Variables declared earlier, not shown here
// Valid YouTube video page
if (isYTVid.test(site)) { // isYTVid is a previously declared regex string
refNotesbtn.click(); // Auto-click the refresh notes button
}
refNotesbtn.addEventListener('click', function() {
videoID = get_videoID();
chrome.runtime.sendMessage({
message: 'get_notes',
payload: videoID
});
});
我现在的问题是,上面显示注解的代码在大多数情况下都能正常工作,但如果我切换到另一个标签,然后切换回YouTube标签并打开扩展,检索注解的函数返回undefined,并显示未找到注解的消息。如果我单击按钮刷新注解,它们会正确显示。如果在插入、编辑或删除功能(这里没有显示)中发生此错误,则可能会对用户造成重大问题,因此我希望在继续操作之前解决此错误。
我注意到错误发生时,也没有显示“已达到预先承诺!”的信息,那么get_notes函数是根本没有被触发,还是在触发后才出现问题?代码墙的问题很抱歉,感谢大家的帮助。
2条答案
按热度按时间hc8w905p1#
由于
db
是异步发现的,因此需要缓存Promise-wrapped(例如const dbPromise = ...
),而不是原始的db
。然后,您可以使用dbPromise.then(db => {...})
(或async/await等价物)可靠地访问db
。我会这样写,代码中有很多解释性注解。
我唯一不确定的部分是
request.onupgradeneeded
和request.onsuccess
之间的相互作用。我假设这些事件中的一个或另一个会触发。如果它们按顺序触发(?),那么代码可能需要稍微不同。cfh9epnr2#
我的建议如下:创建一个简单的promise返回helper函数,用于连接indexedDB。
修改
get_records
以接受数据库参数作为其第一个参数,始终返回promise,并在promise执行器回调函数中执行所有工作。当你需要做某件事时,就撰写作品: