通过Chrome Runtime Messaging从内容脚本访问Service Worker保存的IndexedDB数据

r55awzrz  于 2022-12-09  发布在  IndexedDB
关注(0)|答案(2)|浏览(218)

在Chrome扩展中,我可以通过内容脚本发送的Chrome Runtime Messaging向/从服务人员访问的IndexedDB数据库中添加、更新和删除数据。我的问题是从内容脚本读取完整的表。我创建了console.log()在Chrome Runtime Messaging的sendResponse中发送回属性之前转储该属性,我可以在那里正确地看到数据,但是内容脚本收到了一个undefined。我认为这是因为获取数据的异步特性。我尝试了promises和async/await以及它们的组合,但是除了在内容脚本中从服务工作者返回的消息中得到一个undefined之外,我似乎什么也得不到。我还运行了发回一个测试数组的过程,结果很好--但是接收IndexedDB表数据在消息传递中不起作用。我还尝试对数据进行JSON化,结果也没有帮助。问题是什么?

服务工作者.js

importScripts('modules/idb.js');

var SW = {};

SW.onReady = function(){

  chrome.runtime.onMessage.addListener(function(o, sender, sendResponse) {
    (o.readTable) && sendResponse(SW.readTable(o,sender));
  });

};

SW.readTable = function(o,sender){
  var sTable = o.table;
  new Promise((resolve) => {
    IDB.readTable(sTable,function(asEntries){
      resolve(asEntries);
    });
  }).then((asEntries) => {
console.log('SW asEntries',asEntries); // this shows me valid data in tests
    var o = {};
    // can also change this to fake data with asEntries being a string array and bug goes away in content.js
    o.response = asEntries;
    return o;
  });
};

SW.onReady();

模块/idb.js

var IDB = {};

// Requires storage (or, even better, unlimitedStorage) permission in your manifest.json file.
// Note also that dev console of service worker will not show data -- have to use toolbar button popup panel (if you have one) and 
// dev console from there, or code to access it, which sucks.

IDB.connectStore = function(sTable,sReadWriteSetting,fn){
    var conn = indexedDB.open('unlimitedStorage', 1);
    conn.onupgradeneeded = function(e) {
        var db = e.target.result;
        db.createObjectStore(sTable);
    };
    conn.onsuccess = function(e) {
        var db = e.target.result;
        var tx = db.transaction(sTable,sReadWriteSetting);
        var store = tx.objectStore(sTable);
        fn(db,tx,store);
    };
};

IDB.addToTable = function(sTable,sKey,sVal){
    IDB.connectStore(sTable,'readwrite',function(db,tx,store){
        if ((sKey === undefined) || (sKey === '') || (sKey === null) || (sKey === false)) { // auto key by increment
            var req = store.count();
            req.onsuccess = function(e){
                sKey = e.target.result + 1;
                store.add(sVal,sKey);
                tx.complete;
            }
        } else {
            store.add(sVal,sKey);
            tx.complete;
        }
    });
};

IDB.removeFromTable = function(sTable,sKey){
    IDB.connectStore(sTable,'readwrite',function(db,tx,store){
        store.delete(sKey);
        tx.complete;
    });
};

IDB.readTableByKey = function(sTable,sKey,fn){
    IDB.connectStore(sTable,'readonly',function(db,tx,store){
        var req = store.get(sKey);
        req.onerror = function(e){
            fn(e.target.result);
        }
        req.onsuccess = function(e){
            fn(e.target.result);
        }
    });
};

IDB.readTable = function(sTable,fn){
    IDB.connectStore(sTable,'readonly',function(db,tx,store){
        var req = store.getAll();
        req.onerror = function(e){
            fn(e.target.result);
        }
        req.onsuccess = function(e){
            fn(e.target.result);
        }
    });
};

内容.js**

var CONTENT = {};

CONTENT.onReady = function(){
  var o = {};
  o.readTable = true;
  o.table = 'loadTimes';
  chrome.runtime.sendMessage(o,function(response){
    if (response.response) { // errors here with response property being undefined
      console.log('CONTENT RCVD asEntries',response.response);
    }
  });
};

CONTENT.onReady();
ou6hu8tu

ou6hu8tu1#

与Firefox WebExtensions不同,Chrome扩展API无法处理回调返回的或sendResponse中提供的Promise,https://crbug.com/1185241
readTable中也有一个错误:您需要在new Promise((resolve)之前添加return
解决方案有两个方面:
1.使用回调中的return true以允许异步sendResponse
1.在Promise链的.then内调用sendReponse

chrome.runtime.onMessage.addListener(function(o, sender, sendResponse) {
  if (o.readTable) {
    SW.readTable(o,sender).then(sendResponse);
    return true;
  } else {
    sendResponse(); // Chrome 99-101 bug workaround, https://crbug.com/1304272
  }
});
mmvthczy

mmvthczy2#

请勿使用此答案。此处提供此答案是为了方便后人使用,只是一种变通方法。所选的解决方案有效。

修复方法是在不同的消息线程中返回数据:
1.在SW.readTable()中的service worker中,只需返回变量oo.response = true,然后忽略内容脚本中的响应。
1.在从SW.readTable()返回变量o之前,执行chrome.runtime.sendMessage({readTableResult = true, data: asEntries},function(response){ /* ignore response */});
1.在内容脚本中,忽略从readTable消息返回的任何响应。因此,可以消除if (response.response) {...}条件。
1.在内容脚本中,添加一个包含chrome.runtime.onMessage.addListener(o, sender, sendResponse)的消息监听程序,并查找条件(o.readTableResult)。一旦接收到o.datao.data现在将包含asEntries数据。

相关问题