如何在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
相关产品推荐
相关产品推荐

