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

如何实现Flask后端任务完成后向React.js前端触发回调函数

回答

完全可以实现,因为HTTP默认是单向短连接,没法直接支撑30分钟长链路的回调,你可以从以下3种成熟方案里选适合你当前技术栈的实现:

方案1:WebSocket 双向通信(最灵活的方案)

WebSocket 支持前后端全双工通信,后端可以随时主动给前端推送消息,适合需要双向交互的场景。

实现步骤:

  • Flask端安装flask-socketio库扩展WebSocket能力,React端安装socket.io-client对接
  • 前端触发任务时先建立WebSocket连接,生成唯一的任务ID和当前连接绑定
  • Flask收到任务请求后,将任务投递到后台任务队列(如Celery、RQ,不要直接在请求线程执行,否则会超时阻塞)
  • 任务执行完成后,Flask通过绑定的WebSocket连接向前端推送完成状态和结果,前端收到消息后触发对应回调函数即可

核心代码示例:

Flask端核心逻辑:

from flask import Flask, request
from flask_socketio import SocketIO, emit
from celery import Celery

app = Flask(__name__)
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'
socketio = SocketIO(app, cors_allowed_origins="*")

celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)

@celery.task
def long_time_task(params):
    # 你的30分钟长耗时逻辑写在这里
    return "任务执行完成,结果为xxx"

@app.route('/trigger-task', methods=['POST'])
def trigger_task():
    params = request.json
    task = long_time_task.delay(params)
    return {"task_id": task.id}

@socketio.on('bind_task')
def bind_task(task_id):
    # 后台监听任务状态,完成后推送
    while True:
        task = long_time_task.AsyncResult(task_id)
        if task.state == 'SUCCESS':
            emit('task_finished', task.result)
            break
        socketio.sleep(10)

React端核心逻辑:

import { io } from 'socket.io-client'

function App() {
  const triggerTask = async () => {
    // 1. 触发任务拿到任务ID
    const res = await fetch('你的Flask服务地址/trigger-task', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({/* 你的自定义参数 */})
    })
    const { task_id } = await res.json()
    // 2. 建立WebSocket绑定任务,监听完成通知
    const socket = io('你的Flask服务地址')
    socket.emit('bind_task', task_id)
    socket.on('task_finished', (result) => {
      // 这里写你要触发的回调逻辑
      console.log('任务完成', result)
    })
  }

  return <button onClick={triggerTask}>触发长耗时任务</button>
}

方案2:SSE(服务器发送事件,轻量单向推送方案)

SSE是HTTP原生支持的单向推送机制,只需要服务端向前端推送消息的场景下,比WebSocket更轻量,前端原生支持不需要额外依赖。

实现逻辑:

  • 前端触发任务后拿到返回的任务ID,用原生EventSource接口建立SSE连接
  • Flask端实现SSE接口,挂起连接后监听对应任务的执行状态,任务完成后将结果通过SSE通道推送给前端,前端收到消息后触发回调。

方案3:前端轮询(新手最容易上手的方案)

如果觉得前两种方案的通信逻辑太复杂,30分钟的长耗时任务完全可以用轮询实现,开发成本最低。

实现逻辑:

  • 前端触发任务后,后端立刻返回唯一的任务ID
  • 前端按固定间隔(比如1分钟,30分钟的任务完全不会有太大请求量)向后端发送请求查询该任务的执行状态
  • 后端查询任务队列返回当前状态,前端收到成功状态时触发回调即可

优势:

  • 不需要学习额外的通信协议,代码逻辑直白不容易踩坑
  • 天然支持页面刷新场景,只要把任务ID存在本地存储,刷新后还能接着查询任务进度

注意事项

  • 所有方案都需要把长耗时任务放到后台任务队列执行,绝对不要直接写在Flask的路由处理函数中,Flask默认的单线程处理模式会直接阻塞请求,还会触发网关超时。
  • 建议对任务状态做持久化存储,即使用户中途关闭页面,下次打开还可以追溯任务结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:06:03