Javascript 使用IndexedDB缓存网络请求,并在调用相同的api请求时返回缓存响应
我正在开发一个vue应用程序。我需要在获取响应时缓存api请求,并需要将其存储到indexeddb中。所以,下次如果我再次使用相同的参数调用相同的api服务,它应该返回缓存响应。我已经试着实现了这一点 因此,我创建了indexeddb并创建了一个存储函数,用于存储正确的api请求或响应。通过使用服务工作者获取事件,它将工作或返回缓存的响应 这是我的代码:Javascript 使用IndexedDB缓存网络请求,并在调用相同的api请求时返回缓存响应,javascript,html,vue.js,caching,indexeddb,Javascript,Html,Vue.js,Caching,Indexeddb,我正在开发一个vue应用程序。我需要在获取响应时缓存api请求,并需要将其存储到indexeddb中。所以,下次如果我再次使用相同的参数调用相同的api服务,它应该返回缓存响应。我已经试着实现了这一点 因此,我创建了indexeddb并创建了一个存储函数,用于存储正确的api请求或响应。通过使用服务工作者获取事件,它将工作或返回缓存的响应 这是我的代码: // testing the custom cache response const cacheName ='Testing cache re
// testing the custom cache response
const cacheName ='Testing cache response';
const self = this;
const staticFiles = [
'index.template.html',
'app.js']
const IDBConfig = {
name: 'Cache_responses',
version: 1,
stores: [
{
type: 'request_api',
Path: 'url'
},
{
type: 'response_result',
Path: 'url'
}
]
};
const createIndexedDb = ({name, version, stores}) => {
return new Promise((resolve,reject) => {
const request = self.indexedDB.open(name, version);
request.onupgradeneeded = e => {
const db = e.target.result;
// eslint-disable-next-line array-callback-return
stores.map(({type, Path}) => {
if(!db.objectStoreNames.contains(type)) {
db.createObjectStore(type, {Path});
}
})
}
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
})
};
// correct store for api requests or resposnses
const getStore = (idbName, version) => ({type}, mode='readonly') => {
return new Promise((resolve,reject) => {
const request = self.indexedDB.open(idbName, version);
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(type, mode);
const store = transaction.objectStore(type);
return resolve(store);
}
request.onerror = () => reject(request.error);
})
};
const openStore = getStore(IDBConfig.name, IDBConfig.version);
const cacheApiResponse = async response => {
try {
const store = await openStore(IDBConfig.stores[1], 'readwrite');
store.add(response);
}
catch(error) {
// eslint-disable-next-line no-console
console.log('idb error', error);
}
};
const prefetch = async url => {
const response = await fetch(url);
const clone = response.clone();
const json = await clone.json();
cacheApiResponse({url, json});
return response.json();
};
// eslint-disable-next-line no-shadow
// eslint-disable-next-line consistent-return
// function for api post request
const cacheApiRequest = async request => {
const headers = [...request.headers.entries()].reduce((obj, [key, value]) =>
Object.assign(obj, {[`${key}`]: value}), {});
const serialized = {
headers,
url: request.url,
method: request.method,
mode: request.mode,
credentials: request.credentials,
cache: request.cache,
redirect: request.redirect,
referrer: request.referrer
};
if(request.method !=='GET' && request.method !=='') {
return request.clone().text().then(body => {
serialized.body= body;
})
}
const requestStore = await openStore(IDBConfig.stores[0], 'readwrite');
requestStore.add(serialized)
};
const getPrevCachedResponse = request => {
return new Promise((resolve,reject) => {
openStore(IDBConfig.stores[1]).then(store => {
const cachedRequest = store.get(request.url);
cachedRequest.onsuccess = () => {
return cachedRequest.result === undefined ? resolve(null) : resolve(new Response(JSON.stringify(cachedRequest.result.json)));
};
cachedRequest.onerror = () => {
return reject(cachedRequest.error);
};
})
})
};
const cachingForLaterUse = async request => {
const {method, url} = request;
const requestClone = request.clone();
try {
const response = await fetch(request);
const json = await response.clone().json();
if(method === 'GET') {
cacheApiResponse({url, json});
}
return response;
}
catch(e) {
return method === 'POST' ? cacheApiRequest(requestClone) : new Response(JSON.stringify({message: 'no response'}));
}
};
const getCachedOrNetworkResponse = async request => await getPrevCachedResponse(request) || cachingForLaterUse(request)
const installedEvent = e => {
e.waitUntil(
caches.open(cacheName)
.then(cache => cache.addAll(staticFiles))
);
};
const activateEvent = () => {
if(self.indexedDB) {
createIndexedDb(IDBConfig);
}
};
// eslint-disable-next-line no-shadow
const fetchingEvent = async e => {
const {request} = e;
const {url} = request;
const {pathname} = new URL(url);
if(url.includes('/api')) {
e.respondWith(getCachedOrNetworkResponse(request));
}
else {
e.respondWith(
caches.match(request)
.then(response => response || fetch(request))
);
}
};
self.addEventListener('install', installedEvent);
self.addEventListener('activate', activateEvent);
self.addEventListener('fetch', fetchingEvent);
我遗漏了什么,或者如何简化它以实现缓存api请求并在再次发生相同请求时返回缓存响应
我对indexeddb不太熟悉,所以任何简化的方法都是可以接近的。任何人都有这样的经验。是否有任何方法可以通过在每次调用和接收缓存响应时阻止api请求来提高性能?