在Angular应用程序中,我有一个像这样缓存的URL端点:
// ngsw-config.json
"dataGroups": [{
"name": "api-performance",
"urls": [
"https://my-api.com/v1/languages",
],
"cacheConfig": {
"strategy": "performance",
"maxSize": 300,
"maxAge": "1d"
}
}
]
当客户进行调查过程时,它可以在脱机情况下完美运行。但是在管理面板中,的确,当我尝试更新语言信息时,它确实会更新数据库中的记录,但是当我尝试刷新数据时,它不会将请求发送到我们的端点,而是发送到浏览器中存储的缓存中
这是我尝试过的:
getLanguages(shouldCache: boolean): Promise<any> {
if (shouldCache) {
return this.httpClient.get('https://my-api.com/v1/languages').toPromise();
} else {
const headers = new HttpHeaders({
'Cache-Control': 'no-cache, no-store, must-revalidate, post-check=0, pre-check=0',
'Pragma': 'no-cache',
'Expires': '0'
});
return this.httpClient.get('https://my-api.com/v1/languages', { headers: headers }).toPromise();
}
}
不幸的是,它不起作用。我还考虑过更新缓存,但是我不知道该怎么做。
有人知道如何解决此问题吗?
答案 0 :(得分:1)
您在performance
的1天中使用maxAge
模式,该模式总是从缓存中提供价值(如果有)。您将在一天后看到数据更改。
相反,您可以使用freshness
模式或在maxAge
模式下减小performance
。
您的手动完成请求不适用,因为URL https://my-api.com/v1/languages
已缓存在服务工作者中。请求中的两种缓存操作都不起作用,因为请求缓存和服务工作者缓存是不同的缓存层。
从角度docs:
Angular服务工作者可以使用两种缓存策略中的任何一种来获取数据资源。
性能(默认设置)会针对尽可能快的响应进行优化。如果缓存中存在资源,则使用缓存的版本,并且不发出网络请求。根据maxAge,这会有些陈旧,以换取更好的性能。这适用于不经常更改的资源。例如,用户头像图片。
新鲜度优化了数据流通性,优先从网络中获取请求的数据。只有网络超时(根据超时),请求才会回退到缓存。这对于经常变化的资源很有用;例如帐户余额。
答案 1 :(得分:1)
首先,您需要了解服务工作者层是与前端和服务器分离的。它位于中间,拦截所有网络请求,因此您可以决定如何处理它们。
服务工作者获取事件处理程序只有一个参数,事件。
您可以“解析”该对象以获取有关请求,event.request的信息,并确定应如何处理。
例如,您很可能不想缓存POST,PUT或DELETE请求,因此只需通过调用fetch将那些请求传递到网络即可。仅测试GET请求,即可简化此过程。
self.addEventListener("fetch", event => {
event.respondWith(
if(event.request.mode === "GET") {
//compare URL against rules table
//perform caching strategy for this URL
} else {
return fetch(event);
}
);
});
如果您可能有一个适用于URL的缓存策略,则需要查看可能要应用的策略。 FWIW,我可能会采用大约25种不同的策略,因此我将尽量简化。
这是我将URL与缓存策略进行匹配的方法的示例:
function testRequestRule( request, rules ) {
for ( let i = 0; i < rules.length; i++ ) {
if ( rules[ i ].route && rules[ i ].route.test( request.url ) ) {
return rules[ i ];
} else if ( rules[ i ].destination &&
rules[ i ].destination === request.destination ) {
return rules[ i ];
}
}
}
这是规则对象的外观:
let routeRules = [ {
"route": /img\/products\//,
"strategy": "cacheFallingBackToNetworkCache",
"options": {
cacheName: prodPhotos,
fallback: offlineProductPhoto
}
},....]
然后我将对请求执行所需的策略:
if ( rule.strategy ) {
switch ( rule.strategy ) {
case "cacheFallingBackToNetwork":
return responseManager.cacheFallingBackToNetworkCache(
event.request, rule.cacheName || cacheName,
rule.options.fallback );
case "fetchAndRenderResponseCache":
return responseManager.fetchAndRenderResponseCache( {
request: event.request,
pageURL: rule.options.pageURL,
template: rule.options.template,
api: rule.options.api,
cacheName: rule.cacheName || cacheName
} )
.then( response => {
invalidationManager.cacheCleanUp( rule.cacheName || cacheName );
return response;
} );
case "cacheOnly":
return responseManager.cacheOnly( event.request, rule.cacheName || cacheName )
.then( response => {
invalidationManager.cacheCleanUp( rule.cacheName || cacheName );
return response;
} );
case "networkOnly":
return responseManager.networkOnly( event.request );
case "custom":
return rule.options.handler( event, rule );
default:
return responseManager
.cacheFallingBackToNetworkCache( event.request,
rule.cacheName || cacheName,
rule.options.fallback )
.then( response => {
invalidationManager.cacheCleanUp( rule.cacheName || cacheName );
if ( response ) {
return response;
} else {
return simpleFetch( event );
}
} )
.catch( error => {
console.error( "fetch error: ", error );
console.error( "url: ", event.request.url );
} );
}
} else {
return simpleFetch( event );
}
简而言之,您可以控制每个网络请求的处理方式,这就是服务工作者的美丽。您只需要创建逻辑来处理此问题,就没有神奇的子弹可以培养出色的服务人员。您将必须自己编写代码,当然还要对其进行测试。 :)