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

如何实现Quart应用在后台任务完成后自动重定向用户?

实现Quart后台任务完成后自动跳转页面

因为HTTP是无状态协议,后台任务无法主动触发前端页面的重定向,所以需要通过前端主动查询状态或者WebSocket实时推送两种方式实现,下面是具体方案:

方案一:前端轮询(简单易实现)

1. 新增任务状态存储

用内存字典存储任务状态(单进程部署可用,多进程/分布式建议用Redis):

from uuid import uuid4

# 存储任务状态:key为task_id,value为{"status": "pending"/"completed", "user_id": xxx}
task_status = {}

2. 修改首页路由,生成任务ID并传递

@app.route('/', methods=['POST'])  # 注意指定POST方法,适配表单提交
async def index():
    form = await request.form      
    user_id = int(form['user_id'])
    
    # 生成唯一任务ID
    task_id = str(uuid4())
    # 初始化任务状态为待完成
    task_status[task_id] = {"status": "pending", "user_id": user_id}
    
    # 把task_id传给后台任务
    app.add_background_task(task_to_do, user_id=user_id, task_id=task_id)
    
    # 重定向到加载页面并携带task_id
    return redirect(f'/loading?task_id={task_id}')

3. 修改后台任务,完成后更新状态

async def task_to_do(user_id: int, task_id: str):
    # 模拟耗时抓取操作,替换为实际抓取逻辑
    await asyncio.sleep(60)
    
    # 抓取完成后更新任务状态
    task_status[task_id]["status"] = "completed"
    # 如需存储抓取结果,可在此添加字段,比如 task_status[task_id]["result"] = 抓取数据

4. 新增任务状态查询接口

@app.route('/check-task-status')
async def check_task_status():
    task_id = request.args.get('task_id')
    if not task_id or task_id not in task_status:
        return jsonify({"status": "invalid"})
    return jsonify(task_status[task_id])

5. 加载页面(loading.html)前端逻辑

用JavaScript定时查询状态,完成后自动跳转:

<!DOCTYPE html>
<html>
<head>
    <title>数据抓取中</title>
    <script>
        const urlParams = new URLSearchParams(window.location.search);
        const taskId = urlParams.get('task_id');
        
        // 每2秒查询一次任务状态
        const checkInterval = setInterval(async () => {
            const response = await fetch(`/check-task-status?task_id=${taskId}`);
            const data = await response.json();
            
            if (data.status === 'completed') {
                clearInterval(checkInterval);
                // 跳转到结果页面,可根据实际路由修改
                window.location.href = `/result?user_id=${data.user_id}`;
            }
        }, 2000);
    </script>
</head>
<body>
    <h1>数据抓取中,请稍候...</h1>
</body>
</html>

方案二:WebSocket实时推送(实时性更强)

1. 初始化WebSocket相关存储

from quart import websocket

# 存储WebSocket连接:key为task_id,value为websocket对象
active_connections = {}

2. 修改首页路由(同轮询方案步骤2)

@app.route('/', methods=['POST'])
async def index():
    form = await request.form      
    user_id = int(form['user_id'])
    
    task_id = str(uuid4())
    task_status[task_id] = {"status": "pending", "user_id": user_id}
    
    app.add_background_task(task_to_do, user_id=user_id, task_id=task_id)
    
    return redirect(f'/loading?task_id={task_id}')

3. 修改后台任务,完成后推送消息

async def task_to_do(user_id: int, task_id: str):
    await asyncio.sleep(60)
    
    task_status[task_id]["status"] = "completed"
    
    # 若存在对应WebSocket连接,推送完成信号
    if task_id in active_connections:
        ws = active_connections[task_id]
        try:
            await ws.send_json({"status": "completed", "user_id": user_id})
        except Exception:
            # 连接已关闭,移除无效记录
            del active_connections[task_id]

4. 添加WebSocket路由

@app.websocket('/ws')
async def ws():
    task_id = request.args.get('task_id')
    if not task_id or task_id not in task_status:
        await websocket.close()
        return
    
    # 保存当前连接
    active_connections[task_id] = websocket._get_current_object()
    try:
        # 保持连接存活
        while True:
            await websocket.receive()
    except Exception:
        # 连接关闭时清理记录
        if task_id in active_connections:
            del active_connections[task_id]

5. 加载页面的WebSocket逻辑

<!DOCTYPE html>
<html>
<head>
    <title>数据抓取中</title>
    <script>
        const urlParams = new URLSearchParams(window.location.search);
        const taskId = urlParams.get('task_id');
        
        // 建立WebSocket连接
        const ws = new WebSocket(`ws://${window.location.host}/ws?task_id=${taskId}`);
        
        ws.onmessage = function(event) {
            const data = JSON.parse(event.data);
            if (data.status === 'completed') {
                ws.close();
                window.location.href = `/result?user_id=${data.user_id}`;
            }
        };
        
        ws.onerror = function() {
            console.error('WebSocket连接出错');
        };
    </script>
</head>
<body>
    <h1>数据抓取中,请稍候...</h1>
</body>
</html>

注意事项

  • 内存存储(task_status、active_connections)仅适用于单进程部署,多进程或分布式场景请改用Redis等外部存储。
  • 可定时清理长时间未处理的任务状态,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:20:29