Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/430.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用IndexedDB缓存网络请求,并在调用相同的api请求时返回缓存响应_Javascript_Html_Vue.js_Caching_Indexeddb - Fatal编程技术网

Javascript 使用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

我正在开发一个vue应用程序。我需要在获取响应时缓存api请求,并需要将其存储到indexeddb中。所以,下次如果我再次使用相同的参数调用相同的api服务,它应该返回缓存响应。我已经试着实现了这一点

因此,我创建了indexeddb并创建了一个存储函数,用于存储正确的api请求或响应。通过使用服务工作者获取事件,它将工作或返回缓存的响应

这是我的代码:

// 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请求来提高性能?