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

基于AJAX实现Celery任务轮询的方案咨询

Celery任务进度实时更新方案的问题分析与修正

现有方案的核心问题

你的整体思路方向是对的,但代码存在几个关键缺陷,导致无法实现“实时更新进度”的需求:

  • async_result.get()阻塞请求:这个方法默认会一直等待任务完成才返回结果,直接导致current_data视图的请求被挂起,完全失去了轮询的意义,用户页面会一直处于等待状态,根本拿不到中间进度。
  • 状态判断逻辑不匹配:前端AJAX里判断response.status === 'in_progress',但后端视图根本没返回status字段,只返回了data,导致前端判断永远不成立,逻辑完全失效。
  • 无循环轮询机制:当前AJAX只调用了一次pollTaskStatus,没有在任务未完成时重复发起请求,无法持续获取进度。
  • 进度数据传递缺失:你需要的是任务执行过程中数据库的实时状态,但现有代码只能拿到任务最终返回值,没法获取中间进度。

修正后的实现方案

后端(Django视图+Celery任务)

1. 修改current_data视图,返回任务状态与进度数据

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

def current_data(request):
    task_id = request.GET.get('task_id')
    if not task_id:
        return JsonResponse({'error': 'task_id is required'}, status=400)
    
    async_result = AsyncResult(task_id)
    response_data = {
        'status': async_result.status,  # 状态值包括PENDING/STARTED/PROGRESS/SUCCESS/FAILURE等
        'data': None
    }
    
    if async_result.status == 'SUCCESS':
        # 任务完成,返回最终数据
        response_data['data'] = async_result.get()
    elif async_result.status in ['STARTED', 'PROGRESS']:
        # 读取任务主动更新的进度数据
        response_data['data'] = async_result.info.get('current_data', {})
    
    return JsonResponse(response_data)

2. 修改Celery任务,添加进度更新逻辑

需要让任务在执行过程中主动调用update_state来传递实时进度:

from celery import shared_task
from .models import YourModel  # 替换为你的数据库模型

@shared_task(bind=True)
def prepare_database(self):
    # 模拟耗时的数据库填充逻辑
    total_records = 1000
    for i in range(total_records):
        # 执行数据库插入/更新操作
        YourModel.objects.create(field1=f"value_{i}")
        
        # 每处理100条记录更新一次进度
        if i % 100 == 0:
            current_count = YourModel.objects.count()
            self.update_state(
                state='PROGRESS',
                meta={'current_data': {'count': current_count, 'total': total_records}}
            )
    
    # 任务完成后返回最终数据
    final_data = YourModel.objects.all().values()
    return {
        'count': len(final_data),
        'total': total_records,
        'records': list(final_data)
    }

前端(AJAX轮询+页面更新)

1. 实现循环轮询逻辑

function pollTaskStatus(taskId) {
    $.ajax({
        url: '/current_data/',
        method: 'GET',
        data: { task_id: taskId },
        success: function(response) {
            if (response.status === 'PROGRESS' || response.status === 'STARTED') {
                // 更新页面展示当前进度
                $('#progress-container').html(`已完成 ${response.data.count}/${response.data.total} 条记录`);
                // 1秒后继续轮询
                setTimeout(() => pollTaskStatus(taskId), 1000);
            } else if (response.status === 'SUCCESS') {
                // 任务完成,展示最终结果
                $('#result-container').html(`任务完成!共插入 ${response.data.count} 条记录`);
                // 可在这里渲染详细数据表格
            } else if (response.status === 'FAILURE') {
                $('#error-container').html('任务执行失败,请重试');
            }
        },
        error: function() {
            $('#error-container').html('获取进度失败,稍后重试');
            setTimeout(() => pollTaskStatus(taskId), 3000);
        }
    });
}

$(document).ready(function() {
    const taskId = '{{ task_id }}';
    if (taskId) pollTaskStatus(taskId);
});

2. 模板中添加展示容器

在appname/template.html中添加用于展示进度、结果和错误的元素:

<div id="error-container" style="color: red; margin: 10px 0;"></div>
<div id="progress-container" style="margin: 10px 0;"></div>
<div id="result-container" style="margin: 10px 0;"></div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 21:37:40