MST

星途 面试题库

面试题:React组件在PWA环境下的数据缓存策略与更新机制

当使用React构建PWA应用时,组件可能会依赖一些API数据。阐述你会如何设计数据缓存策略,确保在离线状态下组件能正常使用缓存数据,同时在线时又能及时更新数据,并且要考虑缓存数据的版本控制和一致性问题。
18.6万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

1. 数据缓存策略设计

  • 选择缓存技术:在React PWA中,可使用localStorageIndexedDBCache APIIndexedDB适合大量结构化数据存储,Cache API主要用于缓存网络请求响应,localStorage适合简单少量数据存储。对于API数据,IndexedDB通常是较好选择,因为它能存储复杂数据结构且容量较大。
  • 缓存时机
    • 首次加载:在组件挂载时,先检查缓存中是否有对应数据。如果有,使用缓存数据渲染组件,同时发起网络请求获取最新数据。
    • 更新操作:当组件接收到新的props或状态变化触发重新渲染时,同样先使用缓存数据,然后触发更新数据的网络请求。

2. 离线状态处理

  • 优先读取缓存:在componentDidMountuseEffect钩子函数中,首先尝试从缓存(如IndexedDB)中读取数据。如果成功读取到数据,立即使用这些数据渲染组件,以保证用户能在离线状态下看到内容。
import React, { useEffect, useState } from 'react';
import { readFromCache } from './cacheUtils';

const MyComponent = () => {
  const [data, setData] = useState(null);
  useEffect(() => {
    const fetchData = async () => {
      const cachedData = await readFromCache('apiDataKey');
      if (cachedData) {
        setData(cachedData);
      }
      // 这里同时发起网络请求更新数据(见在线状态处理部分)
    };
    fetchData();
  }, []);

  return (
    <div>
      {data && <p>{JSON.stringify(data)}</p>}
    </div>
  );
};

export default MyComponent;

3. 在线状态处理

  • 后台更新:在获取到缓存数据并渲染组件后,发起网络请求获取最新数据。一旦网络请求成功,将新数据存储到缓存中,并更新组件状态以重新渲染显示最新数据。
import React, { useEffect, useState } from 'react';
import { readFromCache, writeToCache } from './cacheUtils';
import axios from 'axios';

const MyComponent = () => {
  const [data, setData] = useState(null);
  useEffect(() => {
    const fetchData = async () => {
      const cachedData = await readFromCache('apiDataKey');
      if (cachedData) {
        setData(cachedData);
      }
      try {
        const response = await axios.get('/api/data');
        await writeToCache('apiDataKey', response.data);
        setData(response.data);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };
    fetchData();
  }, []);

  return (
    <div>
      {data && <p>{JSON.stringify(data)}</p>}
    </div>
  );
};

export default MyComponent;

4. 缓存数据版本控制

  • 添加版本标识:在缓存数据时,为数据添加版本号。可以在缓存对象中增加一个version字段,每次数据更新时,版本号递增。
const writeToCache = async (key, data) => {
  const cache = await window.indexedDB.open('myCacheDB', 1);
  cache.onupgradeneeded = (event) => {
    const db = event.target.result;
    const objectStore = db.createObjectStore('dataStore', { keyPath: 'id' });
  };
  const tx = cache.transaction(['dataStore'], 'readwrite');
  const store = tx.objectStore('dataStore');
  const existingData = await store.get(key);
  const newData = {
    id: key,
    data,
    version: existingData? existingData.version + 1 : 1
  };
  store.put(newData);
};
  • 版本检查:在读取缓存数据时,检查版本号。如果版本号低于预期(例如,服务端告知了最新版本号),则发起网络请求更新数据。

5. 缓存数据一致性

  • 数据更新策略:为保证一致性,当数据更新时,不仅要更新缓存中的数据,还要确保所有依赖该数据的组件都能及时获取到新数据。可以使用发布 - 订阅模式或Redux等状态管理工具。
    • 发布 - 订阅模式:当数据更新时,发布者通知所有订阅该数据的组件进行更新。
    • Redux:将缓存数据存储在Redux store中,当数据更新时,通过action和reducer更新store,所有订阅该store状态的组件会自动重新渲染。
  • 避免并发冲突:在多个组件同时更新缓存数据时,可能会发生冲突。可以通过使用事务(如IndexedDB中的事务)来确保数据操作的原子性,避免并发冲突。例如,在更新数据时,使用readwrite事务,确保在同一时间只有一个组件能修改缓存数据。