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

Electron JS结合React实现窗口开闭时的HTTP请求方案咨询

问题解决:Electron + React 关闭应用前发起异步HTTP请求

你的核心问题是异步的logout请求还未完成,Electron就已经关闭窗口/退出应用,导致请求被中断。下面是具体的解决方案:


1. 调整主进程的关闭逻辑

核心思路:

  • 阻止默认的窗口关闭/应用退出行为,等待异步请求完成后再手动执行关闭操作。
  • 区分不同平台的行为(macOS下关闭窗口不会直接退出应用,需要额外处理)。

修改后的主进程代码:

const { app, BrowserWindow } = require('electron');
const axios = require('axios');

// 异步注销接口(注意axios.put是小写)
const logout = async (_data) => {
  try {
    return await axios.put('URL_HERE', _data);
  } catch (error) {
    console.error('注销请求失败:', error);
    throw error; // 抛出错误方便上层处理
  }
};

let mainWindow;

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // 根据你的React项目配置调整,若使用contextIsolation需配合preload脚本
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  // 加载你的React应用(本地开发或打包后的路径)
  mainWindow.loadURL('http://localhost:3000'); // 或mainWindow.loadFile('build/index.html')

  // 替换closed事件为close事件,拦截窗口关闭动作
  mainWindow.on('close', async (e) => {
    // 阻止默认关闭行为
    e.preventDefault();

    try {
      // 等待注销请求完成
      await logout(someData);
      console.log('注销成功');
      // 请求完成后销毁窗口
      mainWindow.destroy();
      // macOS以外平台,销毁窗口后退出应用
      if (process.platform !== 'darwin') {
        app.quit();
      }
    } catch (error) {
      console.error('注销失败,将关闭应用');
      // 即使请求失败,也关闭窗口(可根据业务需求调整是否强制关闭)
      mainWindow.destroy();
      if (process.platform !== 'darwin') {
        app.quit();
      }
    }
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

app.whenReady().then(createWindow);

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

// 处理所有窗口关闭时的退出逻辑(针对非macOS平台)
app.on('window-all-closed', async () => {
  if (process.platform !== 'darwin') {
    try {
      await logout(someData);
      console.log('退出前注销成功');
    } catch (error) {
      console.error('退出前注销失败');
    }
    app.quit();
  }
});

// 处理macOS下通过Dock菜单退出的情况
app.on('before-quit', async (e) => {
  if (process.platform === 'darwin') {
    e.preventDefault();
    try {
      await logout(someData);
      console.log('注销成功,即将退出');
      app.quit();
    } catch (error) {
      console.error('注销失败,即将退出');
      app.quit();
    }
  }
});

2. 若注销逻辑在React渲染进程中的处理方式

如果你的logout函数是写在React组件中的(而非主进程),需要通过Electron的IPC通信让主进程等待渲染进程的请求完成:

主进程添加IPC监听:

const { ipcMain } = require('electron');

// 监听渲染进程的注销请求
ipcMain.handle('perform-logout', async (event, data) => {
  try {
    await axios.put('URL_HERE', data);
    return { success: true };
  } catch (error) {
    console.error('注销失败:', error);
    return { success: false, error: error.message };
  }
});

React组件中处理窗口关闭:

import { useEffect } from 'react';
// 注意:新版本Electron需在preload脚本中暴露ipcRenderer,此处为简化写法
const { ipcRenderer } = window.require('electron');

function App() {
  useEffect(() => {
    const handleBeforeUnload = async (e) => {
      e.preventDefault();
      e.returnValue = ''; // 可选:触发浏览器关闭确认提示

      // 向主进程发起注销请求
      const result = await ipcRenderer.invoke('perform-logout', someData);
      if (result.success) {
        // 请求完成后允许关闭窗口
        window.close();
      } else {
        alert('注销失败,请稍后重试');
      }
    };

    window.addEventListener('beforeunload', handleBeforeUnload);
    return () => {
      window.removeEventListener('beforeunload', handleBeforeUnload);
    };
  }, []);

  return <div>你的React应用内容</div>;
}

export default App;

关键注意事项

  • 确保axios已在对应进程中安装(主进程或渲染进程,执行npm install axios)。
  • 若请求耗时较长,可通过IPC通知渲染进程显示“正在注销...”的加载提示,提升用户体验。
  • macOS平台需额外处理before-quit事件,因为用户通过Dock菜单退出时不会触发window-all-closed。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 16:32:48