2017-03-19 153 views
3

有許多例子在那裏初始化服務工作者類似於下面的一個緩存:服務工作者與多個緩存

let cacheName = 'myCacheName-v1'; 
let urlsToCache = ['url1', 'url2', url3']; 

self.addEventListener('install', function (event) { 
    event.waitUntil(
    caches.open(cacheName).then(function (cache) { 
     return cache.addAll(urlsToCache); 
    }).then(function() { 
     return this.skipWaiting(); 
    }) 
); 
}); 

我想對我的服務人員初始化多個緩存。動機是通過其變化趨勢對資產進行分組(例如,靜態應用數據與CSS,JavaScript等)。有了多個緩存,我可以更新個別緩存(通過版本緩存名稱),因爲緩存內的文件會發生更改。理想情況下,我希望建立類似於下面的結構:

let appCaches = [{ 
    name: 'core-00001', 
    urls: [ 
     './', 
     './index.html', etc... 
    ] 
    }, 
    { 
    name: 'data-00001', 
    urls: [ 
     './data1.json', 
     './data2.json', etc... 
    ] 
    }, 
    etc... 
]; 

我最好的嘗試,到目前爲止是類似於:

self.addEventListener('install', function (event) { 
    appCaches.forEach(function (appCache) { 
    event.waitUntil(
     caches.open(appCache.name).then(function (cache) { 
     return cache.addAll(appCache.urls); 
     })); 
    }); 
    self.skipWaiting(); 
}); 

這種做法似乎工作。不過,我仍然是服務工作者和承諾的新手。有些東西告訴我,這種方法有一個缺陷,即我經驗不足以承認。有沒有更好的方法來實現這一點?

回答

4

最好只在處理程序中調用event.waitUntil一次,但好處是讓單個Promise等待相對比較容易。

類似的東西應該工作:

event.waitUntil(Promise.all(
    myCaches.map(function (myCache) { 
    return caches.open(myCache.name).then(function (cache) { 
     return cache.addAll(myCache.urls); 
    }) 
) 
)); 

Promise.all只在陣列的決心,這意味着install處理程序將等到所有緩存被初始化所有承諾後,需要承諾的陣列和解決。

2

謝謝pirxpilot!你的回答,加上JavaScript Promises: an Introduction,以及大量的試驗和錯誤,弄清楚如何將所有這些Promise鏈接在一起導致一個很好的小實現。

我添加了一個要求,只緩存更改。按照最佳做法,舊緩存在「激活」事件期間被刪除。最終產品是:

let cacheNames = appCaches.map((cache) => cache.name); 

self.addEventListener('install', function (event) { 
    event.waitUntil(caches.keys().then(function (keys) { 
    return Promise.all(appCaches.map(function (appCache) { 
     if (keys.indexOf(appCache.name) === -1) { 
     caches.open(appCache.name).then(function (cache) { 
      console.log(`caching ${appCache.name}`); 
      return cache.addAll(appCache.urls); 
     }) 
     } else { 
     console.log(`found ${appCache.name}`); 
     return Promise.resolve(true); 
     } 
    })).then(function() { 
     return this.skipWaiting(); 
    }); 
    })); 
}); 

self.addEventListener('activate', function (event) { 
    event.waitUntil(
    caches.keys().then(function (keys) { 
     return Promise.all(keys.map(function (key) { 
     if (cacheNames.indexOf(key) === -1) { 
      console.log(`deleting ${key}`); 
      return caches.delete(key); 
     } 
     })); 
    }) 
); 
});