You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Electron-Vue应用中保存失败请求并自动重试?

解决方案:Electron-Vue中实现失败请求的本地加密存储与自动重试

我之前做过类似的离线重试需求,给你一套完整的落地思路,完全适配Electron-Vue场景,不用依赖小众npm包,用成熟工具组合就能搞定:

1. 依赖选择:用electron-store做加密本地存储

electron-store是Electron生态里最常用的本地持久化存储库,原生支持加密,比浏览器localStorage更适合桌面应用。先安装它:

npm install electron-store

然后在渲染进程(Vue侧)初始化一个带加密配置的实例:

// src/renderer/utils/retryStore.js
const Store = require('electron-store');
import { v4 as uuidv4 } from 'uuid'; // 生成请求唯一ID用

const retryStore = new Store({
  name: 'failed-upload-requests',
  encryptionKey: 'your-strong-custom-key', // 建议从环境变量读取,不要硬编码
  schema: {
    requests: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          id: { type: 'string' },
          payload: { type: 'object' }, // 存储表单数据
          timestamp: { type: 'number' },
          retryCount: { type: 'number', default: 0 }
        }
      }
    }
  }
});

export default retryStore;

2. 捕获请求失败,存入重试队列

在你的表单上传函数里,捕获所有失败场景(网络错误、HTTP非200状态等),把请求数据写入本地存储:

// src/renderer/components/FormUpload.vue
import retryStore from '../utils/retryStore';

async function handleFormSubmit(formData) {
  try {
    // 你的Google Sheets上传逻辑
    const res = await fetch('your-google-sheets-api-endpoint', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(formData)
    });

    if (!res.ok) throw new Error(`HTTP错误: ${res.status}`);
    // 上传成功后,可清理已完成的重试记录(如果有的话)
    await cleanupCompletedRequests();
  } catch (err) {
    console.error('上传失败,加入本地重试队列:', err);
    // 生成唯一ID用于后续追踪和删除
    const requestId = uuidv4();
    // 将失败请求存入队列
    retryStore.set('requests', [
      ...retryStore.get('requests', []),
      {
        id: requestId,
        payload: formData,
        timestamp: Date.now(),
        retryCount: 0
      }
    ]);
  }
}

3. 监听网络状态,自动触发重试

用Electron主进程的网络事件监听更可靠,同时在渲染进程做补充监听:

主进程侧(处理重试逻辑)

// src/main/index.js
const { app, ipcMain } = require('electron');
const retryStore = require('../renderer/utils/retryStore'); // 注意路径适配

// 监听网络恢复事件
app.on('online', () => {
  console.log('网络已恢复,启动重试任务');
  ipcMain.emit('execute-retry');
});

// 处理重试逻辑
ipcMain.on('execute-retry', async () => {
  const failedRequests = retryStore.get('requests', []);
  if (failedRequests.length === 0) return;

  const remainingRequests = [];
  for (const req of failedRequests) {
    try {
      // 复用上传逻辑,建议把上传封装成通用方法
      const res = await fetch('your-google-sheets-api-endpoint', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(req.payload)
      });

      if (res.ok) {
        console.log(`请求 ${req.id} 重试成功`);
        // 成功则不加入剩余队列,相当于删除该记录
        continue;
      }
      throw new Error(`重试失败,状态码: ${res.status}`);
    } catch (err) {
      console.error(`请求 ${req.id} 重试失败,次数: ${req.retryCount + 1}`, err);
      // 限制最大重试次数,避免无限循环
      if (req.retryCount < 5) {
        remainingRequests.push({
          ...req,
          retryCount: req.retryCount + 1
        });
      } else {
        console.log(`请求 ${req.id} 超过最大重试次数,停止重试`);
        // 这里可选择通知用户或写入错误日志
      }
    }
  }

  // 更新本地存储的重试队列
  retryStore.set('requests', remainingRequests);
});

渲染进程侧(应用启动时检查)

// src/renderer/components/FormUpload.vue
import { ipcRenderer } from 'electron';

mounted() {
  // 应用启动时,如果网络在线就触发一次重试检查
  if (navigator.onLine) {
    ipcRenderer.send('execute-retry');
  }
  // 监听浏览器网络变化事件
  window.addEventListener('online', () => {
    ipcRenderer.send('execute-retry');
  });
}

4. 额外优化建议

  • 密钥安全:不要硬编码加密密钥,可通过keytar存储密钥,或从Electron的环境变量读取,避免泄露。
  • 指数退避重试:给重试设置递增间隔(比如第一次1分钟,第二次2分钟),避免短时间内重复请求给API造成压力。
  • 请求幂等性:确保Google Sheets上传请求是幂等的(比如给表单加唯一标识),避免重复上传同一数据。
  • 日志记录:把重试的成功/失败日志写入本地文件,方便后续排查问题。

这套方案完全满足你「静默处理、加密存储、自动重试」的需求,所有工具都是Electron生态里成熟可靠的,维护成本低。

内容的提问来源于stack exchange,提问作者Praveen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:17:28