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

Quart框架:后台任务完成后如何回调客户端?

解决Quart后台任务完成后回调客户端的问题

要实现请求返回202后,后台任务完成时主动推送结果给客户端,结合你提到的Server-Sent Events(SSE)是合适的方案。核心思路是:用一个存储跟踪任务状态/结果,后台任务完成后更新存储,再通过SSE长连接主动向客户端推送结果。

实现步骤与代码示例

1. 核心改造点

  • 维护一个任务存储(示例用内存字典,生产环境可替换为Redis/数据库)
  • 后台任务完成后更新任务结果
  • 提供SSE端点,客户端连接后等待结果推送

2. 完整代码

import asyncio
from datetime import datetime
import uuid
from quart import Quart, Response

app = Quart(__name__)

# 内存存储任务状态:key=task_id,value={"status": "pending/completed", "result": ...}
tasks = {}

async def background_task(task_id, timeout=10):
    print(f"background task {task_id} started at {datetime.now().strftime('%d/%m/%Y %H:%M:%S')}")
    tasks[task_id]["status"] = "running"
    await asyncio.sleep(timeout) 
    result = "requested task done"
    print(f"background task {task_id} completed at {datetime.now().strftime('%d/%m/%Y %H:%M:%S')}")
    # 任务完成后更新存储
    tasks[task_id]["status"] = "completed"
    tasks[task_id]["result"] = result

@app.route("/", methods=["GET"])
async def main_route():
    print("Hello from main route")
    # 生成唯一任务ID
    task_id = str(uuid.uuid4())
    # 初始化任务状态
    tasks[task_id] = {"status": "pending", "result": None}
    # 启动后台任务
    app.add_background_task(background_task, task_id, 10)
    # 返回202,告知客户端任务ID和SSE查询端点
    return (
        f"Request accepted. Task ID: {task_id}\n"
        f"Connect to /task/{task_id} via SSE to get result.",
        202
    )

@app.route("/task/<task_id>")
async def task_status_sse(task_id):
    # 检查任务是否存在
    if task_id not in tasks:
        return "Task not found", 404

    async def generate_events():
        while True:
            task = tasks[task_id]
            if task["status"] == "completed":
                # 发送结果事件
                yield f"data: {task['result']}\n\n"
                break
            # 每1秒轮询一次任务状态
            await asyncio.sleep(1)

    # 返回SSE响应,设置正确的Content-Type
    return Response(
        generate_events(),
        mimetype="text/event-stream"
    )

if __name__ == "__main__":
    app.run(debug=True)

3. 客户端示例(JavaScript)

客户端通过EventSource连接SSE端点,监听任务结果:

// 假设从服务器返回的响应中拿到task_id
const taskId = "你的任务ID";
const eventSource = new EventSource(`/task/${taskId}`);

eventSource.onmessage = function(event) {
    console.log("任务完成结果:", event.data);
    eventSource.close(); // 收到结果后关闭连接
};

eventSource.onerror = function(error) {
    console.error("SSE连接错误:", error);
    eventSource.close();
};

关键说明

  • 任务存储:示例用内存字典,重启服务器后数据会丢失,生产环境建议用Redis、MongoDB等持久化存储
  • SSE特性:SSE是单向的服务器→客户端推送,适合这种任务完成通知场景,相比轮询更高效
  • 任务状态跟踪:后台任务通过task_id关联存储,完成后更新状态,SSE端点循环检查状态直到完成

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:40:34