如何使用 service worker 响应导航请求?
How to use service worker to respond to navigation requests?
当涉及到缓存时,我试图在 service worker 的帮助下构建一个 PWA,一切都很顺利。但是我运行陷入了一个奇怪的问题。当应用程序处于离线状态时,我无法使用 SW 为我的资产提供服务。似乎SW总是无法响应'navigate'请求。
Uncaught (in promise) TypeError: Failed to fetch
this.addEventListener('fetch', async event => {
event.respondWith(
(async function() {
const requestObj = event.request;
console.log(event);
const urlParts = requestObj.url.split('/');
const fileName = urlParts[urlParts.length - 1];
const fileExtension = fileName.split('.')[fileName.split('.').length - 1];
if (requestObj.method === 'GET') {
if (requestObj.mode === 'navigate' && event.request.headers.get('accept').includes('text/html')) {
console.log('Navigating', requestObj);
const urlParts = requestObj.url.split('/');
console.log(urlParts);
console.log('looking for another option...');
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
});
}
// If its an image, then save it if it is in '.png' format
if (fileExtension === 'jpg' || requestObj.destination === 'image') {
caches
.match(requestObj)
.then(res => {
if (!res) {
throw new TypeError('Bad response status');
} else {
return res;
}
})
.catch(() => {
fetch(requestObj).then(response => {
console.log(response);
if (response.ok || (response.type === 'opaque' && response.status === 0)) {
caches.open('v1').then(cache => {
cache.put(requestObj, response);
});
}
return response;
});
return fetch(requestObj);
});
}
///////////////////////
if (
requestObj.destination === 'script' ||
requestObj.destination === 'style' ||
requestObj.destination === 'font'
) {
caches
.match(requestObj)
.then(response => {
if (response) {
return response;
} else {
throw new TypeError('Bad response status');
}
})
.catch(() => {
fetch(requestObj).then(res => {
if (res.ok) {
caches.open('v1').then(cache => {
cache.put(requestObj, res);
});
}
return res.clone();
});
});
}
//////////////////////
}
return fetch(requestObj);
})()
);
});
我认为您不需要 fetch 事件处理程序中的异步函数,caches.match
returns 一个承诺,因此它足以作为 respondWith
方法的参数
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(function(response) {
const requestObj = event.request;
console.log(event);
const urlParts = requestObj.url.split('/');
const fileName = urlParts[urlParts.length - 1];
const fileExtension = fileName.split('.')[fileName.split('.').length - 1];
if (requestObj.method === 'GET') {
if (requestObj.mode === 'navigate' && event.request.headers.get('accept').includes('text/html')) {
console.log('Navigating', requestObj);
const urlParts = requestObj.url.split('/');
console.log(urlParts);
console.log('looking for another option...');
caches.match(requestObj).then(function(response) {
return response || fetch(event.request);
});
}
// If its an image, then save it if it is in '.png' format
if (fileExtension === 'jpg' || requestObj.destination === 'image') {
caches
.match(requestObj)
.then(res => {
if (!res) {
throw new TypeError('Bad response status');
} else {
return res;
}
})
.catch(() => {
fetch(requestObj).then(response => {
console.log(response);
if (response.ok || (response.type === 'opaque' && response.status === 0)) {
caches.open('v1').then(cache => {
cache.put(requestObj, response);
});
}
return response;
});
return fetch(requestObj);
});
}
///////////////////////
if (
requestObj.destination === 'script' ||
requestObj.destination === 'style' ||
requestObj.destination === 'font'
) {
caches
.match(requestObj)
.then(response => {
if (response) {
return response;
} else {
throw new TypeError('Bad response status');
}
})
.catch(() => {
fetch(requestObj).then(res => {
if (res.ok) {
caches.open('v1').then(cache => {
cache.put(requestObj, res);
});
}
return res.clone();
});
});
}
return fetch(requestObj);
}
})
)
});
当涉及到缓存时,我试图在 service worker 的帮助下构建一个 PWA,一切都很顺利。但是我运行陷入了一个奇怪的问题。当应用程序处于离线状态时,我无法使用 SW 为我的资产提供服务。似乎SW总是无法响应'navigate'请求。
Uncaught (in promise) TypeError: Failed to fetch
this.addEventListener('fetch', async event => {
event.respondWith(
(async function() {
const requestObj = event.request;
console.log(event);
const urlParts = requestObj.url.split('/');
const fileName = urlParts[urlParts.length - 1];
const fileExtension = fileName.split('.')[fileName.split('.').length - 1];
if (requestObj.method === 'GET') {
if (requestObj.mode === 'navigate' && event.request.headers.get('accept').includes('text/html')) {
console.log('Navigating', requestObj);
const urlParts = requestObj.url.split('/');
console.log(urlParts);
console.log('looking for another option...');
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
});
}
// If its an image, then save it if it is in '.png' format
if (fileExtension === 'jpg' || requestObj.destination === 'image') {
caches
.match(requestObj)
.then(res => {
if (!res) {
throw new TypeError('Bad response status');
} else {
return res;
}
})
.catch(() => {
fetch(requestObj).then(response => {
console.log(response);
if (response.ok || (response.type === 'opaque' && response.status === 0)) {
caches.open('v1').then(cache => {
cache.put(requestObj, response);
});
}
return response;
});
return fetch(requestObj);
});
}
///////////////////////
if (
requestObj.destination === 'script' ||
requestObj.destination === 'style' ||
requestObj.destination === 'font'
) {
caches
.match(requestObj)
.then(response => {
if (response) {
return response;
} else {
throw new TypeError('Bad response status');
}
})
.catch(() => {
fetch(requestObj).then(res => {
if (res.ok) {
caches.open('v1').then(cache => {
cache.put(requestObj, res);
});
}
return res.clone();
});
});
}
//////////////////////
}
return fetch(requestObj);
})()
);
});
我认为您不需要 fetch 事件处理程序中的异步函数,caches.match
returns 一个承诺,因此它足以作为 respondWith
方法的参数
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(function(response) {
const requestObj = event.request;
console.log(event);
const urlParts = requestObj.url.split('/');
const fileName = urlParts[urlParts.length - 1];
const fileExtension = fileName.split('.')[fileName.split('.').length - 1];
if (requestObj.method === 'GET') {
if (requestObj.mode === 'navigate' && event.request.headers.get('accept').includes('text/html')) {
console.log('Navigating', requestObj);
const urlParts = requestObj.url.split('/');
console.log(urlParts);
console.log('looking for another option...');
caches.match(requestObj).then(function(response) {
return response || fetch(event.request);
});
}
// If its an image, then save it if it is in '.png' format
if (fileExtension === 'jpg' || requestObj.destination === 'image') {
caches
.match(requestObj)
.then(res => {
if (!res) {
throw new TypeError('Bad response status');
} else {
return res;
}
})
.catch(() => {
fetch(requestObj).then(response => {
console.log(response);
if (response.ok || (response.type === 'opaque' && response.status === 0)) {
caches.open('v1').then(cache => {
cache.put(requestObj, response);
});
}
return response;
});
return fetch(requestObj);
});
}
///////////////////////
if (
requestObj.destination === 'script' ||
requestObj.destination === 'style' ||
requestObj.destination === 'font'
) {
caches
.match(requestObj)
.then(response => {
if (response) {
return response;
} else {
throw new TypeError('Bad response status');
}
})
.catch(() => {
fetch(requestObj).then(res => {
if (res.ok) {
caches.open('v1').then(cache => {
cache.put(requestObj, res);
});
}
return res.clone();
});
});
}
return fetch(requestObj);
}
})
)
});