影片直播原始碼,不同業務場景需選擇不同方案去快取資料

zhibo系统开发發表於2024-04-13

影片直播原始碼,不同業務場景需選擇不同方案去快取資料

在開發影片直播原始碼時,針對不同業務場景,我們應該選擇不同的方案去快取資料。本文就針對最常見的儲存方案和場景做一些分類和介紹一些在 Vue/React 中的高階用法,助力前端開發體驗和應用的穩定性。

前端快取方案

確定不同場景快取方案
1、針對業務列舉、標籤類的,這類的資訊往往都是字典資料,資料量不大並且更新不頻繁,更新前後改動也不大,這類資訊是可以儲存到localStorage中的
2、使用應用期間產生的應用/配置資料:這個資料量不大的情況下就可以使用sessionStorage,否則應該考慮其他狀態管理方案,比如pinia
3、單使用者的基礎資訊這類資訊一般情況是使用者在登陸成功之後後端返回的資訊,這類資訊條目確定,也適合儲存到localStorage
4、根據使用者隔離的快取資料:這個如果用localStorage就不符合我們說的資料條目必須可控原則,應該儲存到indexedDB中
5、隨業務活動增長的資料快取:這個毋庸置疑應該選擇使用indexedDB,localStorage遲早會爆
6、特殊場景的二進位制、媒體資料:這個也應該選擇使用indexedDB

規範
在影片直播原始碼中對於所有快取的key都應該集中管理,數量多了之後要做分級管理,用列舉來管理,避免隨處用隨處起名的壞習慣。

我們可以單獨把專案使用到的常量單獨維護, 從一個出口暴露出去

├── src
│   ├── modules
│   │   ├── constant
│   │   │   └── cache.ts // 快取相關
│   │   │   └── index.ts // 出口

舉個🌰子:

// cache.ts
export enum CacheKeyEnum {
  USER_INFO = 'user-info',
  // ...
}
// index.ts
export * from './cache'
// 使用
import { CacheKeyEnum } from '~/modules/constant'
function getUserCacheInfo() {
  return localStorage.getItem(CacheKeyEnum.USER_INFO)
}

這樣在影片直播原始碼中統一管理key會讓專案更易於維護。

在專案中更簡易、優雅的操作快取

Vue
得益於@vueuse,我們可以用useStorage方法把對sessionStorage和localStorage的操作簡化並且和Vue的響應系統結合:

第一個引數為快取的key,對應setItem的第一個引數,第二個引數為初始資料,返回值為一個Ref型別的物件,可以直接操作state.value = { hello: “hello”, greetinf: “Hi” }響應式更改快取中的值,下面是一些文件中的例子:

import { useStorage } from '@vueuse/core'
// bind object
const state = useStorage('my-store', { hello: 'hi', greeting: 'Hello' })
// bind boolean
const flag = useStorage('my-flag', true) // returns Ref<boolean>
// bind number
const count = useStorage('my-count', 0) // returns Ref<number>
// bind string with SessionStorage
const id = useStorage('my-id', 'some-string-id', sessionStorage) // returns Ref<string>
// delete data from storage
state.value = null

React
同樣的在React中也有類似的庫react-use,其中也有useLocalStorage,對應的用法:

import {useLocalStorage} from 'react-use';
const Demo = () => {
  const [value, setValue] = useLocalStorage('my-key', 'foo');
  return (
    <div>
      <div>Value: {value}</div>
      <button onClick={() => setValue('bar')}>bar</button>
      <button onClick={() => setValue('baz')}>baz</button>
    </div>
  );
};
useLocalStorage(key);
useLocalStorage(key, initialValue);
useLocalStorage(key, initialValue, raw);

key — localStorage 鍵來管理。
initialValue — 要設定的初始化值,如果localStorage中的值為空。
raw — boolean,如果設為 true,鉤子將不會嘗試 JSON 序列化儲存的值。

簡化indexedDB的操作

說了sessionStorage和localStorage的優雅用法,也來說說如何優雅的使用indexedDB

key-value方式的使用
你可以簡單理解為localStorage的非同步版本、可以儲存大體積資料的版本
有這樣一個庫可以幫我們簡化這個操作:localForage

使用方法也很簡單:

import localForage from "localforage";
// 你的專案ID
const PID = "your project's ID"
// 例項
let lfInstance: LocalForage
/** 初始化LF */
export function initLFInstance(): LocalForage {
  if (!lfInstance)
    lfInstance = localforage.createInstance({ name: PID })
  return lfInstance
}
/**
 * 設定或讀取快取資訊, null: 刪除,傳參:更新,不傳參:獲取
 * @param key storage key
 * @param data storage data
 * @returns storage data | null
 */
export function useIndexedDB<T, K extends string>(key: K, data?: T | null): Promise<T | null> {
  if (!lfInstance) {
    console.error('lfInstance is not initialized')
    return Promise.resolve(null)
  }
  else {
    return data === null
      ? (lfInstance!.removeItem(key) as unknown as Promise<null>)
      : data === undefined
        ? lfInstance!.getItem(key)
        : lfInstance!.setItem(key, data)
  }
}

在影片直播原始碼啟動的時候呼叫一次initLFInstance方法,之後就可以用封裝好的useIndexedDB方法來操作indexedDB了

SQL級別的儲存資料
這種可以直接用原生的寫法也可以考慮用Dexie.js來操作,會方便很多,比如前面說的切換使用者資料的快取我們就可以用這個來處理:

構建:

import type { Table } from 'dexie'
import Dexie from 'dexie'
import { IndexedDBKeys } from '../constant'
// 使用者資料表型別
interface IUserData {
  id?: number
  name: string
  phone: string
  age: number
}
export class AppDataDexie extends Dexie {
  userDataDB!: Table<IUserData>
  constructor() {
    super(IndexedDBKeys.UserData)
    this.version(1).stores({
      userDataDB: '++id, name, phone, age',
    })
  }
}
/** 構建DB例項 */
const db = new AppDataDexie()
/** 匯出使用者db操作 */
export const userDB = db.userDataDB

使用

import { userDB } from './db'
userDB.add({ id: 1, name: 'senar', phone: 'xxxx', age: 22 })
// ...更多操作可以檢視文件
// https://dexie.org/docs/Tutorial/Getting-started

其他一些邊界檢測

我們前面說了sessionStorage和localStorage是有5M容量限制的,我們如何知道使用者的使用情況呢?

// 檢測localStorage使用空間
function sieOfLS() {
  return Object.entries(localStorage).map(v => v.join('')).join('').length;
}
// 檢測sessionStorage使用空間
function sieOfSS() {
  return Object.entries(sessionStorage).map(v => v.join('')).join('').length;
}

indexedDB也是可以檢測容量的,可能在safari瀏覽器上有相容性問題,大家也可以參考下:

export async function getCacheUsage() {
  const { quota, usage } = await navigator.storage.estimate()
  const remainingSpace = quota! - usage!
  const unit = 1073741824
  const text = `已使用:${(usage ?? 0) / unit} GB, 剩餘可用快取空間:${remainingSpace / unit} GB`
  console.info(text)
  return remainingSpace
}

總結

前端快取的選型需要貼合影片直播原始碼的業務場景來選擇,以上就是影片直播原始碼,不同業務場景需選擇不同方案去快取資料, 更多內容歡迎關注之後的文章


來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/69978258/viewspace-3012433/,如需轉載,請註明出處,否則將追究法律責任。

相關文章