im trying to use CacheStorage's promises in Angular 5 like in the docs :
let test = caches.open('test');
test.then((result : Cache) => {
result.add('/test.png')
})
but i got :
ERROR Error: Uncaught (in promise): TypeError: the given value is not a Promise
I tryed switching from es5 to es6 in the ts file. But same problem
thanks
I had the same problem in one of my projects. I wanted my application to store some assets in the
CacheStorage
.My code looked something like this:
I got the same Error:
While searching for the problem I found out that Angular is replacing the browser's global
Promise
implementation by it's ownZoneAwarePromise
to keep track of promises. Unfortunately theCacheStorage
somehow expects a nativePromise
instead of Angular'sZoneAwarePromise
and throws an error.I tried to get around this problem by storing the
ZoneAwarePromise
temporarily and reset it with the originalPromise
. This turned out to be tricky, resulting in me giving up to exchange back the implementation.I found two suitable workarounds for this.
Service Worker <=> Client Communication
For my second (and I think better) workaround I open a channel for client <=> service worker communication and let the service worker do the dynamic caching.
Implement the
message
event listener in the service worker.The service worker will listen to the
message
event to receive and cache a list of urls from the client.Add caching for new urls to the client.
This submits a message to the service worker with the list of urls as payload.
Make sure the service worker is active for caching.
I use the
controllerchange
event in the client to trigger re-caching if a new service worker is taking control. (see: service worker lifecycle documentation).Invisible
iframe
My first workaround for this problem is really just a hack but it works for now.
What I'm doing here:
I create a hidden
iframe
and append it to my document. Inside theiframe
Angular is not running and so there is the nativePromise
implementation present. Then I access the cache from the iframe'scontentWindow
object. After successful caching I remove theiframe
.I'm still looking for a better solution.
My next try is to send a message to a service worker and let it trigger the caching of the resources. The service worker has no angular running either.
This is easy to miss -
1) CacheStorage API (or Cache API) are only available on localhost and HTTP/2.
2) For purists reason, prefer to use
window.caches.open(CACHE_NAME)
ascaches
is a singleton instance present inwindow
object.