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

ReactJS中如何轮询API直至Celery异步任务完成?

React轮询Celery异步任务实现方案

首先需要补充状态来跟踪任务状态、结果以及轮询状态,然后通过**递归setTimeout**实现轮询(前端不能用循环sleep,会阻塞主线程),同时注意清理定时器避免内存泄漏。以下是完整实现代码:

import { useEffect, useState } from "react"
import axios from "axios"

function App() {
  const [taskId, setTaskId] = useState("")
  const [taskStatus, setTaskStatus] = useState("PENDING") // 初始为等待状态
  const [taskResult, setTaskResult] = useState(null)
  const [pollingTimer, setPollingTimer] = useState(null) // 存储定时器ID用于清理

  // 启动Celery任务
  const apiToSpawnTask = () => {
    axios.get("http://localhost:8000/spawn_task")
      .then(({data}) => {
        setTaskId(data.task_id)
        setTaskStatus("PENDING") // 重置状态
      })
      .catch(err => console.error("启动任务失败:", err))
  }

  // 查询任务状态
  const checkTaskStatus = () => {
    if (!taskId) return
    
    axios.get(`http://localhost:8000/task-id/${taskId}`)
      .then(({data}) => {
        setTaskStatus(data.status)
        
        // 根据状态处理
        switch(data.status) {
          case "SUCCESS":
            // 任务完成,停止轮询并获取结果
            clearTimeout(pollingTimer)
            getCompletedTaskResult()
            break
          case "FAILURE":
            // 任务失败,停止轮询
            clearTimeout(pollingTimer)
            console.error("任务执行失败")
            break
          default:
            // 任务未完成,继续轮询(间隔2秒,可根据需求调整)
            setPollingTimer(setTimeout(checkTaskStatus, 2000))
        }
      })
      .catch(err => {
        console.error("查询状态失败:", err)
        // 失败后停止轮询,也可根据需求添加重试逻辑
        clearTimeout(pollingTimer)
      })
  }

  // 获取任务结果
  const getCompletedTaskResult = () => {
    axios.get(`http://localhost:8000/get-task-result/${taskId}`)
      .then(({data}) => {
        setTaskResult(data)
        console.log("任务结果:", data)
      })
      .catch(err => console.error("获取结果失败:", err))
  }

  useEffect(() => {
    // 页面加载时启动任务
    apiToSpawnTask()

    // 当taskId生成且任务处于等待状态时,启动第一轮询
    if (taskId && taskStatus === "PENDING") {
      // 延迟1秒启动,避免任务还未注册到Celery
      const timer = setTimeout(checkTaskStatus, 1000)
      setPollingTimer(timer)
    }

    // 组件卸载时清理定时器,防止内存泄漏
    return () => {
      if (pollingTimer) clearTimeout(pollingTimer)
    }
  }, [taskId, taskStatus]) // 依赖taskId和taskStatus,状态变化时重新触发逻辑

  return (
    <div>
      <h2>Celery任务状态: {taskStatus}</h2>
      {taskResult && (
        <div>
          <h3>任务结果:</h3>
          <pre>{JSON.stringify(taskResult, null, 2)}</pre>
        </div>
      )}
    </div>
  )
}

export default App

关键说明:

  • 用**递归setTimeout**替代setInterval:确保上一次状态请求返回后再发起下一次,避免并发请求导致的状态混乱
  • 定时器清理:组件卸载或任务完成/失败时,及时清理定时器,防止内存泄漏
  • 状态跟踪:通过taskStatus和taskResult状态,在页面上实时展示任务进度和结果
  • 错误处理:每个API请求都添加catch,避免前端因接口报错崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 07:55:40