本章会深入讨论 fetch 事件并展示它所提供的诸多用例。
4.1 Fetch API
传统上,从服务器获取数据是通过使用 XMLHttpRequest 对象,也成为 AJAX。
var request
if (window.XMLHttpRequest) {
request = new XMLHttpRequest()
} else {
try {
request = new ActiveXObject('Msxml2.XMLHTTP')
} catch (e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP')
} catch (e) {}
}
}
使用 XMLHttpRequest 对象来编写代码会相当棘手,逻辑越复杂,代码就越复杂。
Fetch API 是 Service Worker 全局作用域的一部分,可以用来在任何 Service Worker 中发起 HTTP 请求。
fetch('/some/url', {
method: 'POST',
headers: {
'auth': '1234'
},
body: JSON.stringify({
name: 'dean',
login: 'dean123'
})
})
.then(function (data) {
console.log('Request success: ', data)
})
.catch(function (error) {
console.log('Request failure: ', error)
})
4.2 fetch 事件
在 Service Worker 中创建自定义 HTTP 响应
self.addEventListener('fetch', function (event) {
if (/\.jpg$/.test(event.request.url)) {
event.respondWith(
new Response('<p>This is a response that comes from your Service Worker!</p>', { header: 'Content-Type': 'text/html' })
)
}
})
Service Worker 生命周期
前文说过,只有当 Service Worker 安装完成并且用户刷新了页面或者跳转到网站的其他页面时,Service Worker 才会激活并开始拦截请求。
self.addEventListener('install', function (event) {
event.waitUntil(self.skipWaiting())
})
skipWaiting() 函数强制等待中的 Service Worker 成为激活的 Service Worker。该函数还可以与 self.clients.claim() 一起使用,以确保底层 Service Worker 的更新立即生效。
self.addEventListener('activate', function (event) {
event.waitUntil(self.clients.claim())
})
4.3 fetch 实战
4.3.1 使用 WebP 图片的示例
支持 WebP 格式的浏览器会在每个 HTTP 请求中添加 accept: image/webp 请求头来告知服务端它支持 WebP 格式。现在 Service Worker 可以拦截请求,将 WebP 图片进行返回。
self.addEventListener('fetch', function (event) {
if (/\.jpg$|.png$/.test(event.request.url)) {
var supportsWebp = false
if (event.request.headers.has(accept)) {
supportsWebp = event.request.headers.get('accept').includes('webp')
}
if (supportsWebp) {
var req = event.request.clone()
var returnUrl = req.url.substr(0, req.url.lastIndexOf('.')) + '.webp'
event.resondWith(
fetch(returnUrl, {
mode: 'no-cors'
})
)
}
}
})
4.3.2 使用 Save-Data 请求头的示例
使用最新版本浏览器,有一个节省流量的选项,启用该功能则会为每个 HTTP 请求添加一个新的请求头 saveData。
self.addEventListener('fetch', function (event) {
if (event.request.headers.get('save-data')) {
// 为了节省流量限制了图标和字体
if (event.request.url.includes('fonts.googleapis.com')) {
// 不返回任何内容
event.respondWith(new Response('', { status: 417, statusText: 'Ignore fonts to save data.' }))
}
}
})



![[译] 终于,JavaScript 有了安全的数组方法](https://img-1252058122.cos.ap-guangzhou.myqcloud.com/blog/article-cover/cmfkkq9a00001uhcg5k63cmt3.jpg)

