This repository has been archived by the owner on Oct 2, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 34
/
service-worker.js
140 lines (122 loc) · 4.35 KB
/
service-worker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* eslint no-var:0, no-console:0 */
// thanks Jake! https://github.com/jakearchibald/simple-serviceworker-tutorial/blob/gh-pages/sw.js
var currentCache = 'JS_AIR'
// Chrome's currently missing some useful cache methods,
// this polyfill adds them.
polyfillCache()
// Here comes the install event!
// This only happens once, when the browser sees this
// version of the ServiceWorker for the first time.
self.addEventListener('install', function onServiceWorkerInstall(event) {
console.log('install event', event)
// We pass a promise to event.waitUntil to signal how
// long install takes, and if it failed
event.waitUntil(
// We open a cache…
caches.open(currentCache).then(function addResourceToCache(cache) {
return cache.addAll([
'/',
])
})
)
})
// The fetch event happens for the page request with the
// ServiceWorker's scope, and any request made within that
// page
self.addEventListener('fetch', function onServiceWorkerFetch(event) {
console.log('fetch event', event)
// Calling event.respondWith means we're in charge
// of providing the response. We pass in a promise
// that resolves with a response object
event.respondWith(
// First we look if we can get the (maybe updated)
// resource from the network
fetch(event.request).then(function updateCacheAndReturnNetworkResponse(networkResponse) {
console.log(`fetch from network for ${event.request.url} successfull, updating cache`)
caches.open(currentCache).then(function addToCache(cache) {
return cache.add(event.request)
})
return networkResponse
}).catch(function lookupCachedResponse(reason) {
// On failure, look up in the Cache for the requested resource
console.log(`fetch from network for ${event.request.url} failed:`, reason)
return caches.match(event.request).then(function returnCachedResponse(cachedResponse) {
return cachedResponse
})
})
)
})
function polyfillCache() {
/* eslint-disable */
if (!Cache.prototype.add) {
Cache.prototype.add = function add(request) {
return this.addAll([request])
}
}
if (!Cache.prototype.addAll) {
Cache.prototype.addAll = function addAll(requests) {
var cache = this
// Since DOMExceptions are not constructable:
function NetworkError(message) {
this.name = 'NetworkError'
this.code = 19
this.message = message
}
NetworkError.prototype = Object.create(Error.prototype)
return Promise.resolve().then(function() {
if (arguments.length < 1) throw new TypeError()
// Simulate sequence<(Request or USVString)> binding:
var sequence = []
requests = requests.map(function(request) {
if (request instanceof Request) {
return request
}
else {
return String(request) // may throw TypeError
}
})
return Promise.all(
requests.map(function(request) {
if (typeof request === 'string') {
request = new Request(request)
}
var scheme = new URL(request.url).protocol
if (scheme !== 'http:' && scheme !== 'https:') {
throw new NetworkError('Invalid scheme')
}
return fetch(request.clone())
})
)
}).then(function(responses) {
// TODO: check that requests don't overwrite one another
// (don't think this is possible to polyfill due to opaque responses)
return Promise.all(
responses.map(function(response, i) {
return cache.put(requests[i], response)
})
)
}).then(function() {
return undefined
})
}
}
if (!CacheStorage.prototype.match) {
// This is probably vulnerable to race conditions (removing caches etc)
CacheStorage.prototype.match = function match(request, opts) {
var caches = this
return this.keys().then(function(cacheNames) {
var match
return cacheNames.reduce(function(chain, cacheName) {
return chain.then(function() {
return match || caches.open(cacheName).then(function(cache) {
return cache.match(request, opts)
}).then(function(response) {
match = response
return match
})
})
}, Promise.resolve())
})
}
}
}