【问题标题】:Service Workers and IndexedDBService Worker 和 IndexedDB
【发布时间】:2018-11-19 20:05:50
【问题描述】:

在一个简单的 JavaScript Service Worker 中,我想在 event.respondWith 之前拦截一个请求并从 IndexedDB 读取一个值

但 IndexDB 的异步特性似乎不允许这样做。

由于 indexedDB.open 是异步的,我们必须等待它,这很好。但是,回调(onsuccess)稍后发生,因此该函数将在等待打开后立即退出。

我发现让它可靠工作的唯一方法是添加:

var wait = ms => new Promise((r, j) => setTimeout(r, ms));
await wait(50)

在我的 readDB 函数结束时强制等待,直到 onsuccess 完成。

这完全是愚蠢的!

请不要试图告诉我有关承诺的事情。它们在这种情况下不起作用。

有人知道我们应该如何正确使用它吗?

这里有示例 readDB(为清楚起见,删除了所有错误检查)。请注意,我们不能在 onsuccess 中使用 await,因此不会等待两个内部 IndexedDB 调用!

async function readDB(dbname, storeName, id) {
    var result;
    var request = await indexedDB.open(dbname, 1); //indexedDB.open is an asynchronous function
    request.onsuccess = function (event) {
        let db = event.target.result;
        var transaction = db.transaction([storeName], "readonly"); //This is also asynchronous and needs await
        var store = transaction.objectStore(storeName);
        var objectStoreRequest = store.get(id); //This is also asynchronous and needs await
        objectStoreRequest.onsuccess = function (event) {
            result = objectStoreRequest.result;
        };
    };

    //Without this wait, this function returns BEFORE the onsuccess has completed
    console.warn('ABOUT TO WAIT'); 
    var wait = ms => new Promise((r, j) => setTimeout(r, ms));
    await wait(50)
    console.warn('WAIT DONE');
    return result;
}

【问题讨论】:

    标签: service-worker


    【解决方案1】:

    请不要试图告诉我有关承诺的事情。它们在这种情况下不起作用。

    ...

    ...

    ...

    我的意思是,他们确实如此。假设您可以将基于 Promise 的 IndexedDB 查找inside 放在 event.respondWith() 中,而不是 before event.respondWith(),至少。 (如果您尝试在调用event.respondWith() 之前之前执行此操作,以确定您是否想要回复,那么您是正确的,因为这是不可能的,因为决定是否调用event.respondWith()需要同步进行。)

    将 IndexedDB 包装在基于 Promise 的接口中并不容易,但https://github.com/jakearchibald/idb 已经完成了艰苦的工作,并且在 service worker 内部运行良好。此外,如果您只需要一个键/值对而不是完整的 IndexedDB 功能集,https://github.com/jakearchibald/idb-keyval 使执行此类操作变得更加容易。

    这是一个示例,假设您对 idb-keyval 没问题:

    importScripts('https://cdn.jsdelivr.net/npm/idb-keyval@3/dist/idb-keyval-iife.min.js');
    
    // Call idbKeyval.set() to save data to your datastore in the `install` handler,
    // in the context of your `window`, etc.
    
    self.addEventListener('fetch', event => {
      // Optionally, add in some *synchronous* criteria here that examines event.request
      // and only calls event.respondWith() if this `fetch` handler can respond.
    
      event.respondWith(async function() {
        const id = someLogicToCalculateAnId();
        const value = await idbKeyval.get(id);
    
        // You now can use `value` however you want.
        const response = generateResponseFromValue(value);
    
        return response;
      }())
    });
    

    【讨论】:

      猜你喜欢
      • 2018-09-29
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-02
      • 2020-02-10
      • 1970-01-01
      相关资源
      最近更新 更多