forked from mapbox/mapbox-gl-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcache_api.html
331 lines (284 loc) · 10.5 KB
/
cache_api.html
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
<!DOCTYPE html>
<html>
<head>
<title>Mapbox GL JS debug page</title>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel='stylesheet' href='../dist/mapbox-gl.css' />
<style>
body { margin: 0; padding: 0; }
html, body, #map { width: 500px; height: 500px; }
</style>
</head>
<body>
<div id='log'>
<div id='result' style='background-color:#fec'>Result: running tests...</div>
</div>
<div id='map'></div>
<script src='../dist/mapbox-gl-dev.js'></script>
<script src='../debug/access_token_generated.js'></script>
<script>
const CACHE_NAME = 'mapbox-tiles';
let map;
let cache;
let numFail = 0;
start(logResult);
function log(pass, message) {
if (!pass) numFail++;
const div = document.createElement('div');
div.innerHTML = (pass ? 'PASS' : 'FAIL') + ' ' + message;
const log = document.getElementById('log');
log.appendChild(div);
}
function catchError(err) {
log(false, err);
}
function logResult() {
const r = document.getElementById('result');
if (numFail === 0) {
r.innerHTML = 'Result: SUCCESS. All tests passed';
r.style.backgroundColor = '#cfc';
} else {
r.innerHTML = 'Result: FAIL. ' + numFail + ' tests failed.';
r.style.backgroundColor = '#fcc';
}
}
async function start(done) {
cache = await caches.open(CACHE_NAME);
storageClearedTest(() => {
initialize(12.5, () => {
testFirstView(() => {
initialize(13, () => {
testSecondView(() => {
initialize(12.5, () => {
testThirdView(() => {
initializeRaster(() => {
testFirstRaster(() => {
initializeRaster(() => {
testSecondRaster(() => {
// move 10 days into the future
moveToFuture(1000 * 60 * 60 * 24 * 10);
initializeRaster(() => {
testThirdRaster(() => {
done();
});
});
});
});
});
});
});
});
});
});
});
});
});
}
function storageClearedTest(callback) {
mapboxgl.clearStorage(function() {
const message = 'Clears cache storage.';
caches.open(CACHE_NAME).catch(catchError).then(cache_ => {
cache = cache_;
cache.keys().then(function(keys) {
log(keys.length === 0, message);
callback();
}).catch(catchError);
});
});
}
function initialize(zoom, onLoad) {
if (map) map.remove();
map = window.map = new mapboxgl.Map({
container: 'map',
zoom,
center: [-77.01866, 38.888],
style: 'mapbox://styles/mapbox/streets-v10',
interactive: false,
hash: false
});
map.on('style.load', function() {
// add traffic layer that shouldn't be cached because of short expiry
map.addLayer({
"id": "traffic",
"source": {
"url": "mapbox://mapbox.mapbox-traffic-v1",
"type": "vector"
},
"source-layer": "traffic",
"type": "line",
"paint": {
"line-width": 1.5,
"line-color": "red"
}
});
// add third party source that shouldn't be cached
map.addLayer({
"id": "mapillary",
"type": "line",
"source": {
"type": "vector",
"tiles": ["https://d25uarhxywzl1j.cloudfront.net/v0.1/{z}/{x}/{y}.mvt"],
"minzoom": 6,
"maxzoom": 14
},
"source-layer": "mapillary-sequences",
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-opacity": 0.6,
"line-color": "rgb(53, 175, 109)",
"line-width": 2
}
});
map.on('load', onLoad);
});
}
function checkNotCached(keys) {
// check that no resources that shouldn't be cached are cached
const dontCache = ['traffic', 'style', 'fonts', 'd25uarhxywzl1j.cloudfront.net'];
for (const urlSubstring of dontCache) {
log(!matchURL(keys, urlSubstring), "Does not cache wrong resource: " + urlSubstring);
}
}
function testFirstView(done) {
cache.keys().catch(catchError).then(keys => {
log(keys.length === 4, "keys.length = 4");
// check for expected cache entries
const expected = [
"mapbox.mapbox-streets-v7/12/1171/1566.vector.pbf",
"mapbox.mapbox-streets-v7/12/1171/1567.vector.pbf",
"mapbox.mapbox-streets-v7/12/1172/1566.vector.pbf",
"mapbox.mapbox-streets-v7/12/1172/1567.vector.pbf",
];
for (const expect of expected) {
log(matchURL(keys, expect), "Caches correct resource: " + expect);
}
checkNotCached(keys);
// lower cache limits so we can more easily test eviction
map._setCacheLimits(6, 0);
done();
});
}
function testSecondView(done) {
// wait 1 second to give the map a chance to evict from the cache
setTimeout(() => {
cache.keys().catch(catchError).then(keys => {
// some tiles were evicted!
log(keys.length === 6, "Enforces cache size limit: keys.length = 6");
// all the most recent tiles are in the cache
const expected = [
"mapbox.mapbox-streets-v7/13/2342/3133.vector.pbf",
"mapbox.mapbox-streets-v7/13/2342/3134.vector.pbf",
"mapbox.mapbox-streets-v7/13/2343/3133.vector.pbf",
"mapbox.mapbox-streets-v7/13/2343/3134.vector.pbf",
];
for (const expect of expected) {
log(matchURL(keys, expect), "Evicts correct tiles: still has " + expect);
}
checkNotCached(keys);
done();
});
}, 1000);
}
function testThirdView(done) {
// wait 1 second to give the map a chance to evict from the cache
setTimeout(() => {
caches.open(CACHE_NAME).catch(catchError).then(cache => {
cache.keys().catch(catchError).then(keys => {
// some tiles were evicted!
log(keys.length === 6, "Enforces cache size limit: keys.length = 6");
// check that the cache entries are ordered in order of most least use
[13, 13, 12, 12, 12, 12].forEach((z, i) => {
const correctZoom = keys[i].url.indexOf('/' + z + '/') > 0;
log(correctZoom, 'Maintains LRU order: cache entry ' + i + ' has correct zoom level (' + z + ')');
});
// all the most recent tiles are in the cache
const expected = [
"mapbox.mapbox-streets-v7/12/1171/1566.vector.pbf",
"mapbox.mapbox-streets-v7/12/1171/1567.vector.pbf",
"mapbox.mapbox-streets-v7/12/1172/1566.vector.pbf",
"mapbox.mapbox-streets-v7/12/1172/1567.vector.pbf",
];
for (const expect of expected) {
log(matchURL(keys, expect), "Evicts correct tiles: still has " + expect);
}
checkNotCached(keys);
done();
});
});
}, 1000);
}
function initializeRaster(done) {
if (map) map.remove();
map = new mapboxgl.Map({
container: 'map',
zoom: 0,
center: [137.9150899566626, 36.25956997955441],
style: 'mapbox://styles/mapbox/satellite-v9'
});
map.on('load', done);
}
const expectedRasterURL = 'https://api.mapbox.com/v4/mapbox.satellite/1/0/0';
let rasterTileExpiry;
function testFirstRaster(done) {
caches.open(CACHE_NAME).catch(catchError).then(cache => {
fuzzyMatchAll(cache, expectedRasterURL, matches => {
const match = matches[0];
rasterTileExpiry = match && match.headers.get('Expires');
log(matches.length === 1, 'Caches raster tile.' + matches.length + ' ' + rasterTileExpiry);
done();
});
});
}
function testSecondRaster(done) {
caches.open(CACHE_NAME).catch(catchError).then(cache => {
fuzzyMatchAll(cache, expectedRasterURL, matches => {
// check that the tile in the cache after the second map load is the same as after the
// first one. No new tile was loaded or cached.
const match = matches[0];
const newExpiry = match && match.headers.get('Expires');
log(matches.length === 1 && rasterTileExpiry === newExpiry, 'Reuses cached raster tile without refetching.' + matches.length + ' ' + newExpiry);
done();
});
});
}
function testThirdRaster(done) {
caches.open(CACHE_NAME).catch(catchError).then(cache => {
fuzzyMatchAll(cache, expectedRasterURL, matches => {
// check that the tile in the cache after the second map load is the same as after the
// first one. No new tile was loaded or cached.
const match = matches[0];
const newExpiry = match && match.headers.get('Expires');
log(matches.length === 1 && rasterTileExpiry !== newExpiry, 'Replaces expired raster tile with new version.' + matches.length + ' ' + newExpiry);
done();
});
});
}
function fuzzyMatchAll(cache, url, callback) {
cache.keys().catch(catchError).then(keys => {
for (const key of keys) {
if (key.url.indexOf(url) >= 0) {
return cache.matchAll(key.url).catch(catchError).then(callback);
}
}
return callback([]);
});
}
function moveToFuture(skip) {
Date._now = Date.now;
Date.now = function () {
return this._now() + skip;
};
}
function matchURL(keys, s) {
for (const key of keys) {
if (key.url.indexOf(s) >= 0) return true;
}
return false;
}
</script>
</body>
</html>