带有CacheStorage的Angular 5 [英] Angular 5 with CacheStorage

查看:141
本文介绍了带有CacheStorage的Angular 5的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

im试图像文档中一样在Angular 5中使用CacheStorage的Promise:

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')
    })

但是我得到了:

ERROR Error: Uncaught (in promise): TypeError: the given value is not a Promise

我尝试在ts文件中从es5切换到es6.但是同样的问题

I tryed switching from es5 to es6 in the ts file. But same problem

谢谢

推荐答案

我在我的一个项目中遇到了同样的问题.我希望我的应用程序将某些资产存储在CacheStorage中.

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:

window.caches.open(CACHE_NAME)
  .then(cache => cache.addAll(resources))
  .catch(err => console.log('error while caching', err));

我遇到了同样的错误:

ERROR Error: Uncaught (in promise): TypeError: the given value is not a Promise

在搜索问题时,我发现Angular正在用自己的ZoneAwarePromise替换浏览器的全局Promise实现,以跟踪承诺.不幸的是,CacheStorage某种程度上期望本机Promise而不是Angular的ZoneAwarePromise并引发错误.

While searching for the problem I found out that Angular is replacing the browser's global Promise implementation by it's own ZoneAwarePromise to keep track of promises. Unfortunately the CacheStorage somehow expects a native Promise instead of Angular's ZoneAwarePromise and throws an error.

我试图通过暂时存储ZoneAwarePromise并将其重置为原始的Promise来解决此问题.事实证明这很棘手,导致我放弃了换回实施.

I tried to get around this problem by storing the ZoneAwarePromise temporarily and reset it with the original Promise. This turned out to be tricky, resulting in me giving up to exchange back the implementation.

我为此找到了两个合适的解决方法.

I found two suitable workarounds for this.

第二次(而且我认为更好)解决方法,我打开了客户端< =>服务工作者通信的渠道,并让服务工作者进行动态缓存.

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.

  1. 在服务工作者中实现message事件侦听器.

服务工作者将侦听message事件,以接收并缓存来自客户端的网址列表.

The service worker will listen to the message event to receive and cache a list of urls from the client.

self.addEventListener('message', event => {
  const urls = event.data;

  if (!urls) {
    event.waitUntil(Promise.reject('nothing to cache'));
    event.ports[0].postMessage(false);
  }
  else {
    event.waitUntil(
      caches.open(version)
        .then(cache => cache.addAll(urls))
        .then(self.skipWaiting())
        .then(() => console.log('dynamic urls cached'))
    );
    event.ports[0].postMessage(true);
  }
});

  • 为客户端添加新网址的缓存.

  • Add caching for new urls to the client.

    这会将URL列表作为有效内容提交给服务人员一条消息.

    This submits a message to the service worker with the list of urls as payload.

    function addToCache(urls: string[]): Promise<any> {
      return new Promise((resolve, reject) => {
        let messageChannel = new MessageChannel();
        messageChannel.port1.onmessage = function(event) {
          if (event.data.error) reject(event.data.error);
          else resolve(event.data);
        };
    
        if (!navigator.serviceWorker.controller) reject('no service worker contoller found')
        else navigator.serviceWorker.controller.postMessage(urls, [messageChannel.port2]);
      });
    }
    

  • 确保服务工作者处于活动状态以进行缓存.

  • Make sure the service worker is active for caching.

    如果新的服务工作者正在控制,我会在客户端中使用controllerchange事件来触发重新缓存. (请参阅:服务人员的生命周期文档).

    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).

    const resources = ['some/url/to/cache.png', 'another/url/to/cache.css']
    
    navigator.serviceWorker.addEventListener('controllerchange', () => 
      addToCache(resources)
        .then(data => console.log('urls cached', data))
        .catch(err => console.log('error while caching', err))
    );
    

  • 隐形iframe

    我针对此问题的第一个解决方法实际上只是一个hack,但目前可以使用.

    Invisible iframe

    My first workaround for this problem is really just a hack but it works for now.

    const hiddenFrame = document.createElement('iframe');
    hiddenFrame.style.display = 'none';
    document.documentElement.appendChild(hiddenFrame);
    
    hiddenFrame.contentWindow.caches.open(CACHE_NAME)
      .then(cache => cache.addAll(resources))
      .then(() => document.documentElement.removeChild(hiddenFrame))
      .catch(err => console.log('error while caching', err));
    

    我在这里做什么:

    我创建了一个隐藏的iframe并将其附加到我的文档中.在iframe中,Angular没有运行,因此存在本机Promise实现.然后,我从iframe的contentWindow对象访问缓存.成功缓存后,删除iframe.

    I create a hidden iframe and append it to my document. Inside the iframe Angular is not running and so there is the native Promise implementation present. Then I access the cache from the iframe's contentWindow object. After successful caching I remove the iframe.

    我仍在寻找更好的解决方案.

    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.

    这篇关于带有CacheStorage的Angular 5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆