从崩溃到自愈:Electron应用零代码实现自动重启机制

从崩溃到自愈:Electron应用零代码实现自动重启机制

【免费下载链接】electron-quick-start Clone to try a simple Electron app 【免费下载链接】electron-quick-start 项目地址: https://gitcode.com/gh_mirrors/el/electron-quick-start

你是否遇到过Electron应用突然崩溃的情况?用户工作中断、数据可能丢失、支持工单激增——这些问题不仅影响用户体验,更耗费开发者大量精力。本文将基于gh_mirrors/el/electron-quick-start项目,教你如何在不修改核心业务逻辑的前提下,为应用添加崩溃自动恢复功能,让你的桌面应用拥有企业级的稳定性。

读完本文你将掌握:

  • 3行代码实现Electron应用崩溃监听
  • 跨平台兼容的自动重启策略
  • 崩溃日志记录与用户通知最佳实践
  • 基于main.js的完整实现方案

崩溃恢复的工作原理

Electron应用由主进程(Main Process)和渲染进程(Renderer Process)组成。当任何一个进程意外退出时,我们需要:

  1. 捕获进程崩溃事件
  2. 保存必要的用户数据
  3. 重启应用并恢复工作状态

Electron进程模型

实现步骤:3行核心代码改造

步骤1:监听渲染进程崩溃事件

打开项目的main.js文件,在创建窗口的代码后添加崩溃监听:

// 在createWindow函数后添加
app.on('renderer-process-crashed', (event, webContents, killed) => {
  console.log(`Renderer process crashed: ${killed ? 'killed' : 'crashed'}`);
  // 重启应用逻辑将在这里实现
});

步骤2:实现安全重启机制

为了避免无限重启循环,我们需要添加重启延迟和次数限制。修改main.js

let restartAttempts = 0;
const MAX_RESTARTS = 3;
const RESTART_DELAY = 2000; // 2秒延迟

app.on('renderer-process-crashed', (event, webContents, killed) => {
  if (restartAttempts < MAX_RESTARTS) {
    restartAttempts++;
    console.log(`Renderer crashed, restarting (${restartAttempts}/${MAX_RESTARTS})`);
    
    setTimeout(() => {
      // 关闭所有现存窗口
      BrowserWindow.getAllWindows().forEach(window => window.close());
      // 创建新窗口
      createWindow();
    }, RESTART_DELAY);
  } else {
    console.log('Max restart attempts reached');
    // 显示错误对话框
    dialog.showErrorBox('应用错误', '应用程序遇到问题,已多次尝试恢复但失败。请重启应用。');
  }
});

步骤3:添加崩溃日志记录

为了便于调试,我们需要记录崩溃信息。首先安装日志模块:

npm install electron-log --save

然后在main.js顶部引入并配置:

const log = require('electron-log');
log.transports.file.resolvePath = () => path.join(__dirname, 'logs/main.log');
log.info('App started');

完整实现代码

修改后的main.js完整代码如下:

// Modules to control application life and create native browser window
const { app, BrowserWindow, dialog } = require('electron');
const path = require('node:path');
const log = require('electron-log');

// 配置日志
log.transports.file.resolvePath = () => path.join(__dirname, 'logs/main.log');
log.info('Application started');

let restartAttempts = 0;
const MAX_RESTARTS = 3;
const RESTART_DELAY = 2000;

function createWindow() {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  });

  // and load the index.html of the app.
  mainWindow.loadFile('index.html');

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()
  
  // 监听渲染进程控制台日志
  mainWindow.webContents.on('console-message', (event, level, message) => {
    log.info(`Renderer log: ${message}`);
  });
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow();

  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit();
});

// 渲染进程崩溃处理
app.on('renderer-process-crashed', (event, webContents, killed) => {
  const reason = killed ? 'killed' : 'crashed';
  log.error(`Renderer process ${reason}, restart attempts: ${restartAttempts}`);

  if (restartAttempts < MAX_RESTARTS) {
    restartAttempts++;
    
    // 显示崩溃通知
    dialog.showMessageBox({
      type: 'error',
      title: '应用崩溃',
      message: '应用遇到问题需要重启',
      detail: `这是第 ${restartAttempts} 次尝试,最多尝试 ${MAX_RESTARTS} 次`
    }).then(() => {
      setTimeout(() => {
        // 关闭所有窗口并重启
        BrowserWindow.getAllWindows().forEach(window => window.close());
        createWindow();
      }, RESTART_DELAY);
    });
  } else {
    log.error('Max restart attempts reached');
    dialog.showErrorBox('严重错误', '应用程序无法恢复,请重启应用或联系支持。');
  }
});

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

测试与验证

为了验证崩溃恢复功能是否正常工作,你可以:

  1. renderer.js中添加一个崩溃测试按钮:
// 添加到renderer.js
document.addEventListener('DOMContentLoaded', () => {
  const crashButton = document.createElement('button');
  crashButton.textContent = '测试崩溃';
  crashButton.style.marginTop = '20px';
  crashButton.onclick = () => {
    // 故意引发崩溃
    process.crash();
  };
  document.body.appendChild(crashButton);
});
  1. 运行应用:
npm start
  1. 点击"测试崩溃"按钮,应用应该会显示错误提示并自动重启。

进阶优化

数据持久化与恢复

对于需要保存用户数据的应用,可以在preload.js中添加自动保存功能:

// 在preload.js中添加
window.addEventListener('beforeunload', () => {
  // 保存用户数据到本地存储
  const userData = { /* 用户数据 */ };
  localStorage.setItem('appState', JSON.stringify(userData));
});

崩溃日志分析

通过package.json配置日志轮转:

{
  "scripts": {
    "start": "electron .",
    "log": "electron-log show"
  }
}

总结

本文基于gh_mirrors/el/electron-quick-start项目,实现了一个健壮的Electron应用崩溃恢复机制。通过监听渲染进程崩溃事件、实现智能重启策略和完善的用户通知系统,你的应用可以在遇到问题时自动恢复,大大提升用户体验。

关键要点:

  • 使用renderer-process-crashed事件监听崩溃
  • 实现重启次数限制避免无限循环
  • 添加用户友好的崩溃通知
  • 记录详细日志便于问题诊断

这个方案只需修改main.js文件,不影响现有业务逻辑,适合快速集成到任何Electron项目中。

点赞收藏本文,下次你的Electron应用崩溃时,就不会手忙脚乱了!关注我们获取更多Electron开发技巧。

【免费下载链接】electron-quick-start Clone to try a simple Electron app 【免费下载链接】electron-quick-start 项目地址: https://gitcode.com/gh_mirrors/el/electron-quick-start

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值