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

Angular CLI(TypeScript)实现多Celery任务状态定时轮询方案咨询

问题描述

我用Django做后端,需要每3秒轮询多个Celery任务的状态,比如有4个任务ID:

  • 3099023
  • 3493494
  • 4309349
  • 5498458
    要求针对每个ID每3秒调用一次HTTP GET接口查询状态,直到该任务状态变为FINISHED就停止对它的轮询。有没有简便的实现方式?

我之前试过的步骤:

  1. 遍历所有任务ID
  2. 为每个ID创建定时器
  3. 在每个定时器里发起HTTP请求轮询对应ID的状态
  4. 若响应状态未完成则继续轮询,否则停止

简便实现方案

方案1:前端集中批量轮询(推荐)

不用给每个任务单独开定时器,而是用一个全局定时器批量查询所有未完成任务的状态,能减少HTTP请求数量,避免多定时器的资源浪费:

  1. 维护一个待轮询的任务ID列表,初始为所有需要监控的ID
  2. 每隔3秒发起一次批量查询请求(后端需提供批量查询接口)
  3. 后端接口接收多个任务ID,返回每个任务的状态
  4. 前端收到响应后,将状态为FINISHED的任务从待轮询列表中移除
  5. 当待轮询列表为空时,停止定时器

核心代码示例(前端JS)

// 待轮询的任务ID列表
let pendingTaskIds = ['3099023', '3493494', '4309349', '5498458'];
let pollTimer;

function pollTaskStatuses() {
  if (pendingTaskIds.length === 0) {
    clearInterval(pollTimer);
    return;
  }

  // 发起批量查询请求
  fetch(`/api/tasks/status/?ids=${pendingTaskIds.join(',')}`, {
    method: 'GET'
  })
  .then(response => response.json())
  .then(statuses => {
    // 过滤出未完成的任务ID
    pendingTaskIds = pendingTaskIds.filter(taskId => {
      const status = statuses[taskId];
      return status !== 'FINISHED';
    });
  })
  .catch(error => console.error('轮询出错:', error));
}

// 启动轮询,3秒一次
pollTimer = setInterval(pollTaskStatuses, 3000);
// 立即执行一次,避免等待3秒才开始
pollTaskStatuses();

Django后端批量查询接口示例

from django.http import JsonResponse
from celery.result import AsyncResult

def task_status_batch(request):
    task_ids = request.GET.get('ids', '').split(',')
    statuses = {}
    for task_id in task_ids:
        result = AsyncResult(task_id)
        statuses[task_id] = result.status
    return JsonResponse(statuses)

方案2:单任务独立轮询(保留原思路优化)

如果需要给每个任务单独处理,可以用闭包维护每个任务的状态,避免全局变量混乱:

function startPollingTask(taskId) {
  const timer = setInterval(() => {
    fetch(`/api/tasks/status/${taskId}/`)
    .then(response => response.json())
    .then(data => {
      if (data.status === 'FINISHED') {
        clearInterval(timer);
        console.log(`任务 ${taskId} 已完成`);
      }
    })
    .catch(error => {
      console.error(`轮询任务 ${taskId} 出错:`, error);
      clearInterval(timer); // 出错时停止该任务的轮询
    });
  }, 3000);
}

// 为每个任务启动轮询
['3099023', '3493494', '4309349', '5498458'].forEach(startPollingTask);

额外优化建议

  • 后端可以缓存任务状态,避免每次都直接查询Celery backend,提升性能
  • 轮询间隔可动态调整,比如初始1秒一次,后续改为5秒,降低请求压力
  • 内部系统可考虑用WebSocket推送任务状态,完全替代轮询,效率更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 06:20:58