@@ -17,6 +17,72 @@ const MAX_CONCURRENT_REQUESTS = 6;
1717let activeRequests = 0 ;
1818const requestQueue = [ ] ;
1919
20+
21+ // --- IndexedDB persistent cache (works on HTTP & HTTPS) ---
22+ const SDF_DB_NAME = 'maptalks-sdf-cache' ;
23+ const SDF_STORE_NAME = 'sdf' ;
24+ const SDF_DB_VERSION = 1 ;
25+ let _sdfDB = null ;
26+ let _sdfDBReady = null ; // shared promise
27+
28+ function _getCacheKey ( url ) {
29+ // Strip query parameters so tokens/timestamps don't break matching
30+ try {
31+ const u = new URL ( url , typeof location !== 'undefined' ? location . href : undefined ) ;
32+ return u . origin + u . pathname ;
33+ } catch ( e ) {
34+ return url . split ( '?' ) [ 0 ] ;
35+ }
36+ }
37+
38+ function _openSdfDB ( ) {
39+ if ( _sdfDBReady ) return _sdfDBReady ;
40+ _sdfDBReady = new Promise ( ( resolve , reject ) => {
41+ if ( typeof indexedDB === 'undefined' ) {
42+ reject ( new Error ( 'IndexedDB not available' ) ) ;
43+ return ;
44+ }
45+ const req = indexedDB . open ( SDF_DB_NAME , SDF_DB_VERSION ) ;
46+ req . onupgradeneeded = ( ) => {
47+ const db = req . result ;
48+ if ( ! db . objectStoreNames . contains ( SDF_STORE_NAME ) ) {
49+ db . createObjectStore ( SDF_STORE_NAME ) ;
50+ }
51+ } ;
52+ req . onsuccess = ( ) => {
53+ _sdfDB = req . result ;
54+ resolve ( _sdfDB ) ;
55+ } ;
56+ req . onerror = ( ) => reject ( req . error ) ;
57+ } ) ;
58+ return _sdfDBReady ;
59+ }
60+
61+ function _idbGet ( key ) {
62+ return _openSdfDB ( ) . then ( db => {
63+ return new Promise ( ( resolve , reject ) => {
64+ const tx = db . transaction ( SDF_STORE_NAME , 'readonly' ) ;
65+ const store = tx . objectStore ( SDF_STORE_NAME ) ;
66+ const req = store . get ( key ) ;
67+ req . onsuccess = ( ) => resolve ( req . result ) ; // ArrayBuffer or undefined
68+ req . onerror = ( ) => reject ( req . error ) ;
69+ } ) ;
70+ } ) ;
71+ }
72+
73+ function _idbPut ( key , value ) {
74+ return _openSdfDB ( ) . then ( db => {
75+ return new Promise ( ( resolve , reject ) => {
76+ const tx = db . transaction ( SDF_STORE_NAME , 'readwrite' ) ;
77+ const store = tx . objectStore ( SDF_STORE_NAME ) ;
78+ const req = store . put ( value , key ) ;
79+ req . onsuccess = ( ) => resolve ( ) ;
80+ req . onerror = ( ) => reject ( req . error ) ;
81+ } ) ;
82+ } ) ;
83+ }
84+ // -------------------------------------------------------
85+
2086function enqueueSDFRequest ( url , resolve , reject ) {
2187 if ( activeRequests < MAX_CONCURRENT_REQUESTS ) {
2288 executeSDFRequest ( url , resolve , reject ) ;
@@ -40,41 +106,33 @@ function executeSDFRequest(url, resolve, reject) {
40106 processNextSDFRequest ( ) ;
41107 } ;
42108
43- if ( typeof caches !== 'undefined' ) {
44- caches . match ( url ) . then ( cachedResponse => {
45- if ( cachedResponse ) {
46- return cachedResponse . arrayBuffer ( ) . then ( buffer => {
47- resolve ( buffer ) ;
48- onComplete ( ) ;
49- } ) ;
50- } else {
51- fetchAndCacheSDF ( url , resolve , reject , onComplete ) ;
52- }
53- } ) . catch ( ( ) => {
54- fetchAndCacheSDF ( url , resolve , reject , onComplete ) ;
55- } ) ;
56- } else {
57- fetchAndCacheSDF ( url , resolve , reject , onComplete ) ;
58- }
109+ const cacheKey = _getCacheKey ( url ) ;
110+
111+ _idbGet ( cacheKey ) . then ( buffer => {
112+ if ( buffer ) {
113+ // Cache hit — return a copy so the buffer can be transferred
114+ resolve ( buffer instanceof ArrayBuffer ? buffer . slice ( 0 ) : buffer ) ;
115+ onComplete ( ) ;
116+ } else {
117+ fetchAndCacheSDF ( url , cacheKey , resolve , reject , onComplete ) ;
118+ }
119+ } ) . catch ( ( ) => {
120+ // IndexedDB unavailable or error — fall back to network
121+ fetchAndCacheSDF ( url , cacheKey , resolve , reject , onComplete ) ;
122+ } ) ;
59123}
60124
61- function fetchAndCacheSDF ( url , resolve , reject , onComplete ) {
125+ function fetchAndCacheSDF ( url , cacheKey , resolve , reject , onComplete ) {
62126 fetch ( url )
63127 . then ( response => {
64128 if ( ! response . ok ) {
65129 throw new Error ( `HTTP ${ response . status } ` ) ;
66130 }
67- if ( typeof caches !== 'undefined' ) {
68- const clone = response . clone ( ) ;
69- caches . open ( 'maptalks-sdf-cache' ) . then ( cache => {
70- cache . put ( url , clone ) ;
71- } ) . catch ( e => {
72- console . warn ( 'Failed to cache SDF in caches API:' , e ) ;
73- } ) ;
74- }
75131 return response . arrayBuffer ( ) ;
76132 } )
77133 . then ( buffer => {
134+ // Store in IndexedDB (fire-and-forget)
135+ _idbPut ( cacheKey , buffer . slice ( 0 ) ) . catch ( ( ) => { } ) ;
78136 resolve ( buffer ) ;
79137 onComplete ( ) ;
80138 } )
0 commit comments