带有CacheStorage的Angular 5 [英] Angular 5 with CacheStorage
问题描述
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.
-
在服务工作者中实现
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屋!