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

Electron JS后台运行耗时任务及前端展示进度的实现方案咨询

技术选型结论

优先使用 child_process(子进程)方案,次选 Node.js 多线程(Worker Threads),完全不推荐 Service Workers。

选型原因

  • Service Workers 是浏览器端用于离线缓存、网络代理的技术,无法访问 Node.js 原生 API,无法满足本地大文件读取、SFTP 连接的需求,直接排除。
  • Worker Threads 适合纯 JS 实现的 CPU 密集型运算,但如果要复用你已经稳定的 Python 处理逻辑,或者任务涉及大量系统级 IO 操作,灵活性远不如 child_process。
  • child_process 完全独立于 Electron 主进程、渲染进程运行,不会阻塞 UI 交互,就算处理逻辑崩溃也不会拖垮整个客户端,同时可以直接调用你已经写好的 Python 脚本,无需重新用 JS 复刻一遍成熟的 xlsx 处理、SFTP 自动重连逻辑,开发成本最低。

具体实现步骤

1. 主进程侧封装任务调度逻辑

主进程维护全局任务队列,统一管理任务状态、调度子进程运行,同时负责和渲染进程做IPC通信同步状态:

// 主进程核心代码示例
import { spawn } from 'child_process'
import { ipcMain, BrowserWindow } from 'electron'

// 任务类型定义
interface Task {
  id: string
  type: 'xlsx-convert' | 'sftp-sync'
  status: 'waiting' | 'running' | 'done' | 'error'
  // 剩余待处理数量,用于右上角数字展示
  remainingCount: number
}

// 全局任务队列
let globalTaskQueue: Task[] = []
// 你的应用主窗口实例
let mainWindow: BrowserWindow | null

// 监听渲染进程发起的任务创建请求
ipcMain.handle('task:create', (_, taskParams) => {
  const newTask: Task = {
    id: Math.random().toString(36).slice(2, 10),
    type: taskParams.type,
    status: 'waiting',
    remainingCount: taskParams.totalCount
  }
  globalTaskQueue.push(newTask)
  // 同步最新任务列表到渲染进程
  syncTaskListToRenderer()
  // 执行下一个待运行任务
  runPendingTask()
  return newTask.id
})

// 执行待处理任务
function runPendingTask() {
  // 可自行控制同时运行的任务数量,比如最多同时跑2个
  const runningTaskCount = globalTaskQueue.filter(t => t.status === 'running').length
  if (runningTaskCount >= 2) return

  const pendingTask = globalTaskQueue.find(t => t.status === 'waiting')
  if (!pendingTask) return

  pendingTask.status = 'running'
  syncTaskListToRenderer()

  // 启动Python子进程执行处理逻辑
  const childProcess = spawn('python', [
    // 替换为你本地的Python处理脚本路径
    './python-scripts/handler.py',
    // 传入任务参数
    JSON.stringify(pendingTask)
  ])

  // 监听子进程输出的进度信息
  childProcess.stdout.on('data', (data) => {
    try {
      const progressInfo = JSON.parse(data.toString().trim())
      pendingTask.remainingCount = progressInfo.remainingCount
      syncTaskListToRenderer()
    } catch (e) {
      // 处理非JSON格式的日志输出
      console.log('子进程日志:', data.toString())
    }
  })

  // 子进程执行结束
  childProcess.on('close', (code) => {
    pendingTask.status = code === 0 ? 'done' : 'error'
    syncTaskListToRenderer()
    // 继续执行下一个任务
    runPendingTask()
  })
}

// 同步任务列表到渲染进程
function syncTaskListToRenderer() {
  mainWindow?.webContents.send('task:update', [...globalTaskQueue])
}

2. React 渲染进程侧逻辑

你已经打通了 IPC 通信,直接监听主进程推送的任务更新事件即可:

// React 全局状态管理示例(用useContext或者Redux都可以)
import { useEffect, useState } from 'react'
import { ipcRenderer } from 'electron'

interface Task {
  id: string
  type: 'xlsx-convert' | 'sftp-sync'
  status: 'waiting' | 'running' | 'done' | 'error'
  remainingCount: number
}

export function useTaskManager() {
  const [taskList, setTaskList] = useState<Task[]>([])

  useEffect(() => {
    // 监听主进程的任务更新事件
    const removeListener = ipcRenderer.on('task:update', (_, newTaskList) => {
      setTaskList(newTaskList)
    })
    return () => removeListener()
  }, [])

  // 右上角运行中任务数量
  const runningTaskCount = taskList.filter(t => t.status === 'running').length

  // 创建新任务的方法
  const createTask = async (type: Task['type'], totalCount: number) => {
    await ipcRenderer.invoke('task:create', { type, totalCount })
  }

  return { taskList, runningTaskCount, createTask }
}

你可以把这个hook放到全局状态里,右上角的数字标记直接取runningTaskCount展示,任务列表页直接渲染taskList的所有任务状态即可,进度条可以直接用假的无限动画,也可以根据剩余数量计算比例展示。

3. Python 脚本改造

只需要在你原有Python处理逻辑中,每完成一段任务(比如处理完1个xml文件、1个xlsx sheet)就往标准输出打印一行JSON格式的进度信息即可,记得加flush=True避免输出缓存:

import json
import sys

# 原有处理逻辑不变,每完成一个任务加一行输出
# 假设当前剩余待处理数量为remaining
print(json.dumps({"remainingCount": remaining}), flush=True)

备选全JS实现方案

如果你不想依赖Python,要全JS栈实现,可以把上述的child_process替换为Node.js Worker Threads,把xlsx处理、SFTP逻辑放到Worker线程中运行,每处理完一段进度就给主进程发消息,后续的状态同步逻辑和上面完全一致。

内容的提问来源于stack exchange,提问作者4 Leave Cover

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 08:57:02