Отвечая на запрос выборки через кеш или indexedDB
Я пытаюсь заставить работника службы реагировать на события выборки в зависимости от типа сделанного запроса. Для статических ресурсов я использую кеш:
// TODO: make cache update when item found
const _fetchOrCache = (cache, request) => {
return cache.match(request).then(cacheResponse => {
// found in cache
if (cacheResponse) {
return cacheResponse
}
// has to add to cache
return fetch(request)
.then(fetchResponse => {
// needs cloning since a response works only once
cache.put(request, fetchResponse.clone())
return fetchResponse
});
}).catch(e => { console.error(e) })
}
для ответов API я уже связал IndexedDB с IndexedDB Джейка Арчибальда. Обещал возвращать контент, подобный этому:
const fetchAllItems = () => {
return self.idbPromise
.then(conn => conn.transaction(self.itemDB, 'readonly'))
.then(tx => tx.objectStore(self.itemDB))
.then(store => store.getAll())
.then(storeContents => JSON.stringify(storeContents));
}
когда я вызываю все в сервисном работнике, часть кеша работает, но indexedDB сбоит, выдавая ошибку, которую он не может получить по адресу API:
self.addEventListener("fetch", event => {
// analyzes request url and constructs a resource object
const resource = getResourceInfo(event.request.url);
// handle all cachable requests
if (resource.type == "other") {
event.respondWith(
caches.open(self.cache)
.then(cache => _fetchOrCache(cache, event.request))
);
}
// handle api requests
if (resource.type == "api") {
event.respondWith(
new Response(fetchAllItems());
);
}
});
Мои вопросы будут следующими:
1.) Есть ли смысл разделять хранение запросов на выборку, как это?
2.) Как заставить работать часть indexedDB?
1 ответ
Хороший улов на использовании обещания Джейка Арчибальдса на основе IDB. Есть много способов установить его idb. Самое быстрое - скачать где-нибудь файл idb.js (это библиотека). Затем импортируйте его в первую строку в сервисном сервисе likeso:
importScripts('./js/idb.js');
.....
//SW installation event
self.addEventListener('install', function (event) {
console.log("[ServiceWorker] Installed");
});
//SW Actication event (where we create the idb)
self.addEventListener('activate', function(event) {
console.log("[ServiceWorker] Activating");
createIndexedDB();
});
.....
//Intercept fetch events and save data in IDB
.....
//IndexedDB
function createIndexedDB() {
self.indexedDB = self.indexedDB || self.mozIndexedDB || self.webkitIndexedDB || self.msIndexedDB;
if (!(self.indexedDB)) { console.console.log('IDB not supported'); return null;}
return idb.open('mydb', 1, function(upgradeDb) {
if (!upgradeDb.objectStoreNames.contains('items')) {
upgradeDb.createObjectStore('items', {keyPath: 'id'});
}
});
}
Судя по коду, который вы вставили выше для получения данных IDB, мне неясно, что именно является idbPromise... Вы уверены, что объявили эту переменную?
Вы должны иметь что-то вроде этого
importScripts('./js/idb.js');
//...
//createIdb and store
//...
var idbPromise = idb.open('mydb');
//and after that you have your code like idbPromise.then().then()...
Таким образом, вы создаете IDB и таблицы во время активации ПО. После этого вы перехватываете события извлечения и начинаете использовать indexeddb, как в уроках, которые вы видели.
Удачи