Search code examples
javascriptpromiseservice-workerindexeddbweb-worker

Returning Response object with JSON from service worker


I am trying to hook into the fetch request for some JSON and check if the data is in IndexedDB to get it before going to the network. Something odd is happening with my promises not resolving I think.

Here is my code:

event.respondWith(async function() {
        var data = {success:true, msg:'', data: []};

        localforage.iterate(function(value, key) {
            data.data.push([key, value])
        })
        if (data.data.length > 0) {
            return await new Response(JSON.stringify(data),{
                headers: { "Content-Type" : "application/json" }
            });
        }

        let response = await fetch(event.request)
        // clone response as it can only be used once and needs to be returned for client fetch
        let responseData = await response.clone().json()
        await responseData.data.forEach(function (todo) {
            localforage.setItem(todo[0], todo[1])
        })

        return response

    }())

However, my front end gets an empty response object when the if resolves true (data in IndexedDB). It's as if my response object is being created before the IndexedDB promise resolves.


Solution

  • It's a bit of a guess without being able to run the code but

    • I think you need to wait for localforage.iterate since it returns a promise
    • I think you also need to wait for localforage.setItem since it returns a promise too - using Promise.all and map should handle that for you

      var data = {success:true, msg:'', data: []};
      
      await localforage.iterate((value, key) => {
          data.data.push([key, value])
      })
      if (data.data.length > 0) {
          return new Response(JSON.stringify(data),{
              headers: { "Content-Type" : "application/json" }
          });
      }
      
      let response = await fetch(event.request)
      // clone response as it can only be used once and needs to be returned for client fetch
      let responseData = await response.clone().json()
      await Promise.all(responseData.data.map(todo => {
          return localforage.setItem(todo[0], todo[1]);
      }));
      
      return response;