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
相关产品推荐
相关产品推荐

