用IndexedDB保存并导出前端日志TS版,适用原生JS,Vue和React

环境

  • Windows 10
  • Node.js v18.0.0
  • Yarn (用npmpnpm也没问题)
  • VS Code
  • Chrome

前言

  • 本教程直接给出方法,复制即可用。需要一定的indexedDB的基础知识
  • 方法中并没有使用异步,根据需要自行添加即可
  • 虽然本教程给只出了VueReact两个JS框架的例子,但是其中函数也可以直接用于原生TS和JS

安装第三方库

  • file-saver:导出文件用,@types/file-saver是他的类型库
  • dayjs:时间库,可以根据个人喜好选择其他时间库
yarn add -D file-saver @types/file-saver dayjs

Vue.js版本

App.vue

React.js版本

App.tsx

// 导入第三方库
import dayjs from "dayjs";
import { saveAs } from "file-saver";
​
function App() {
  // 定义常量
  const dataBaseVer: number = 1; // 版本
  const dataBaseName: string = "MyIndexedDB"; // db名
  const dataBaseStore: string = "MyStore"; // store名
  const dataBaseKeyPath: string = "key"; // 主key
  const dataBaseLimit: number = 10000; // 数据条数限制
  const filename: string = `log_${dayjs().format("YYYYMMDD")}.txt`; // 导出的log文件名
​
  // 创建indexedDB
  const createIndexedDB = (): void => {
    const indexed: IDBOpenDBRequest = indexedDB.open(dataBaseName, dataBaseVer);
​
    // 第一次执行,因为没有版本,所以会触发onupgradeneeded事件,此时新建store并追加主key
    indexed.onupgradeneeded = (event: IDBVersionChangeEvent): void => {
      const db: IDBDatabase = (event.target as IDBOpenDBRequest).result;
      if (!db.objectStoreNames.contains(dataBaseStore)) {
        db.createObjectStore(dataBaseStore, {
          keyPath: dataBaseKeyPath,
        });
      }
    };
​
    // 创建失败
    indexed.onerror = (): void => {
      console.log("Indexed Start Error");
    };
  };
​
  // 添加log
  const addLog = (log: string): void => {
    // 获取log时间戳
    const time = dayjs().format("YYYY-MM-DD-HH:mm:ss:SSS");
    const random = Math.ceil(Math.random() * 999);
    const timeStamp = time + "_" + random + "Z";
​
    // 打开db
    const indexed: IDBOpenDBRequest = indexedDB.open(dataBaseName);
    indexed.onsuccess = (event: Event): void => {
      const db: IDBDatabase = (event.target as IDBOpenDBRequest).result;
      const trans: IDBTransaction = db.transaction(dataBaseStore, "readwrite");
      const store: IDBObjectStore = trans.objectStore(dataBaseStore);
      const count: IDBRequest = store.count();
​
      // 计算记录的数量,添加前先检查是否超过限制
      count.onsuccess = (): void => {
        // 没超过就添加
        if (Number(count.result) <= dataBaseLimit) {
          //以主键log为key,把时间戳和log作为value,插入数据库
          store.put({ [dataBaseKeyPath]: `[${timeStamp}] : ${log}` });
          return;
        } else {
          // 没超过就删除最老的一条
          store.openCursor().onsuccess = (event: Event): void => {
            const cursor: any = (event.target as IDBRequest).result;
            if (cursor) {
              cursor.delete();
            }
          };
        }
      };
​
      // 计算记录的数量失败
      count.onerror = (): void => {
        console.log("Count Error");
      };
    };
​
    // db打开失败
    indexed.onerror = (): void => {
      console.log("Indexed Open Error");
    };
  };
​
  // 读取log
  const readDBandExport = (): void => {
    let tmp: string[] = [];
​
    // 打开db
    const indexed: IDBOpenDBRequest = indexedDB.open(dataBaseName);
    indexed.onsuccess = (event: Event): void => {
      const db: IDBDatabase = (event.target as IDBOpenDBRequest).result;
      const trans: IDBTransaction = db.transaction(dataBaseStore, "readonly");
      const store: IDBObjectStore = trans.objectStore(dataBaseStore);
​
      // 遍历数据
      store.openCursor().onsuccess = (event: Event): void => {
        const cursor: any = (event.target as IDBRequest).result;
        // 如果遍历项有数据就放入tmp,然后继续
        if (cursor) {
          tmp.push(cursor.key);
          tmp.push("\r\n");
          cursor.continue();
        } else {
          // 如果遍历项没有数据,说明遍历结束,这时新建blob对象
          const blob: Blob = new Blob(tmp, {
            type: "text/plain;charset=utf-8",
          });
​
          // 导出文件
          saveAs(blob, filename);
        }
      };
​
      // 遍历数据失败
      store.openCursor().onerror = (): void => {
        console.log("OpenCursor Error");
      };
    };
​
    // db打开失败
    indexed.onerror = (): void => {
      console.log("Indexed Open Error");
    };
  };
​
  // 删除数据库
  const deleteIndexedDB = (): void => {
    const indexed: IDBOpenDBRequest = indexedDB.deleteDatabase(dataBaseName);
​
    // 删除成功
    indexed.onsuccess = (): void => {
      console.log("Delete Success");
    };
​
    // 删除失败
    indexed.onerror = (): void => {
      console.log("Delete Error");
    };
  };
​
  // 调用
  createIndexedDB();
  // 测试
  addLog("テスト");
​
  return (
    
     

React.js

                     
); } ​ export default App;

验证(以Vue.js为例)

启动项目后,发现数据库已经建立

用IndexedDB保存并导出前端日志TS版,适用原生JS,Vue和React_第1张图片

点击addLog添加测试数据,然后按readDBandExport导出

用IndexedDB保存并导出前端日志TS版,适用原生JS,Vue和React_第2张图片

查看导出的文件,成功

用IndexedDB保存并导出前端日志TS版,适用原生JS,Vue和React_第3张图片

最后

如果需要结合捕获console.log使用,请使用下面的函数

// log捕获
const catchConsoleLog = () => {
  console.oldLog = console.log;
​
  console.log = (log: string) => {
    // 打印捕获的log
    console.oldLog(log);
    addLog(log);
  };
};
​
// 使用
catchConsoleLog()

你可能感兴趣的:(用IndexedDB保存并导出前端日志TS版,适用原生JS,Vue和React)