How to store response in indexed db during a fetch event

Viewed 213

So during a fetch event I have to capture all the data and store it in indexed db. If I try the below code I am getting error like this:

DOMException: Failed to execute 'put' on 'IDBObjectStore': Response object could not be cloned.

What I want to acheive?

  1. Store all my response in indexdb
  2. Able to get data from it in case if my offline from indexed db
  3. If there is no data in my db fallback to html page.
self.addEventListener("fetch", (event) => {
  event.respondWith(
    new Promise((resolve,reject) => {
      if (navigator.onLine) {
        return fetch(event.request).then((response) => {
           dbRequest = indexedDB.open("CacheDB", 1);
          dbRequest.onupgradeneeded = function (e) {
            const db = e.target.result;
            if (!db.objectStoreNames.contains("CacheStore")) {
              db.createObjectStore("CacheStore");
            }
          };
          dbRequest.onsuccess = function (e) {
            const db = e.target.result;
            const tx = db.transaction("CacheStore", "readwrite");
            const store = tx.objectStore("CacheStore");
            console.log(response,event);
            try
            {
              const request = store.put(**response.clone()**`enter code here`);
              console.log("I am here")
              request.onsuccess = function (e) {
                console.log("Successfully cached!!");
                resolve(response);
              };
              request.onerror = function (e) {
                console.log("Error occures while storing =>", e);
              };
            }
            catch(err)
            {
              console.log("err =>",err);
              resolve(response);
            }
          
          };

          dbRequest.onerror = function (e) {
            console.log("Error occured while creating DB =>", e);
          };
          console.log("sending response");
          
        });
      } else {
        const dbRequest = indexedDB.open("CacheDB", 1);
        dbRequest.onsuccess = function (e) {
          const db = e.target.result;
          const tx = db.transaction("CacheStore", "readwrite");
          const store = tx.objectStore("CacheStore");
          const request = store.get(event.request.url);
          request.onsuccess = function (e) {
            console.log("db cahce.. =>", e);
            return request.result[0];
          };
          request.onerror = function (e) {
            console.log("Error occures while getting =>", e);
          };
        };
      }
    })
  );
});

1 Answers

When objects are stored in Indexed DB they are serialized, which is basically the first half of what used to be called the "structured clone" algorithm, described here: https://html.spec.whatwg.org/multipage/structured-data.html#safe-passing-of-structured-data

The error is telling you that a Response object can't be cloned (serialized/deserialized) - you can also get that error with this code:

window.postMessage(new Response)

... which means that Response objects don't support serialization. To postMessage() or store a Response in IndexedDB you'll need to extract the properties you want to serialize into an object that can be serialized. e.g. a plain JS object holding the headers and response body as a Blob

Related