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

Node.js & Express 长耗时3D模型生成API进度返回方案咨询

长耗时3D模型生成API的进度返回机制与实现方案

针对你的长耗时3D模型生成API,有几种成熟的进度返回机制,以下是具体实现方案和浏览器端读取方式:

一、可行的进度返回机制

1. 分阶段异步API(推荐,兼容性最好)

将整个流程拆分为任务提交、进度查询、结果获取三个独立接口,避免长连接占用资源。

2. Server-Sent Events (SSE)

基于HTTP的单向推送协议,服务端可保持连接并持续发送进度事件,适合不需要双向交互的场景。

3. WebSocket

全双工通信协议,支持服务端主动推送进度,同时允许客户端中途发送取消、调整参数等指令,适合交互需求复杂的场景。

4. 简单轮询(低成本快速实现)

客户端定期调用进度查询接口,实现简单但会产生冗余请求,适合小型项目或原型验证。


二、具体实现细节

1. 分阶段异步API实现

  • 任务提交接口:
    客户端发起POST请求后,服务端立即返回202 Accepted状态码,同时返回唯一taskId(如UUID),后台启动异步任务处理3D模型生成。
    # 服务端示例(Python/Flask)
    @app.post("/api/3d-model/generate")
    def submit_task():
        params = request.get_json()
        task_id = str(uuid.uuid4())
        # 存入Redis:任务状态初始化为pending,进度0%
        redis_client.set(f"task:{task_id}", json.dumps({
            "status": "pending",
            "percentage": 0,
            "is_completed": False,
            "success": False,
            "result": None,
            "error": None
        }))
        # 启动后台异步任务(如用Celery)
        generate_3d_model.delay(task_id, params)
        return {"taskId": task_id}, 202
    
  • 进度查询接口:
    客户端通过taskId查询任务进度,服务端从缓存/数据库中读取并返回当前状态。
  • 结果获取接口:
    任务完成后,客户端通过该接口获取3D模型文本或错误信息。

2. SSE实现

服务端保持HTTP连接,通过SSE格式持续发送进度数据:

# 服务端示例(Python/Flask)
@app.get("/api/3d-model/generate-sse")
def generate_with_sse():
    params = request.args.to_dict()
    def generate_progress():
        # 模拟3D模型生成步骤
        steps = ["拓扑构建", "纹理映射", "模型优化", "导出"]
        for i, step in enumerate(steps):
            progress = (i+1)/len(steps)*100
            # SSE格式:data: {JSON数据}\n\n
            yield f'data: {json.dumps({"type": "progress", "percentage": progress, "status": step})}\n\n'
            time.sleep(60)  # 模拟耗时步骤
        # 发送完成结果
        yield f'data: {json.dumps({"type": "complete", "modelText": "3D模型文本内容"})}\n\n'
    return Response(generate_progress(), mimetype="text/event-stream")

3. WebSocket实现

服务端与客户端建立WebSocket连接,实时推送进度:

# 服务端示例(Python/FastAPI)
@app.websocket("/api/3d-model/generate-ws")
async def generate_with_websocket(websocket: WebSocket):
    await websocket.accept()
    params = await websocket.receive_json()
    # 模拟生成步骤
    steps = ["拓扑构建", "纹理映射", "模型优化", "导出"]
    try:
        for i, step in enumerate(steps):
            progress = (i+1)/len(steps)*100
            await websocket.send_json({
                "type": "progress",
                "percentage": progress,
                "status": step
            })
            await asyncio.sleep(60)
        # 发送完成结果
        await websocket.send_json({
            "type": "complete",
            "modelText": "3D模型文本内容"
        })
    except Exception as e:
        await websocket.send_json({
            "type": "error",
            "error": str(e)
        })
    finally:
        await websocket.close()

三、浏览器端读取进度的方式

1. 分阶段异步API的客户端实现

async function start3DModelGeneration(params) {
    // 提交任务
    const initRes = await fetch("/api/3d-model/generate", {
        method: "POST",
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify(params)
    });
    if (initRes.status !== 202) throw new Error("任务提交失败");
    const { taskId } = await initRes.json();

    // 定时查询进度
    const progressInterval = setInterval(async () => {
        const progressRes = await fetch(`/api/3d-model/progress/${taskId}`);
        const progressData = await progressRes.json();
        
        console.log(`进度:${progressData.percentage}% | 状态:${progressData.status}`);
        
        if (progressData.is_completed) {
            clearInterval(progressInterval);
            if (progressData.success) {
                const resultRes = await fetch(`/api/3d-model/result/${taskId}`);
                const modelText = await resultRes.text();
                // 处理3D模型文本
                console.log("生成完成:", modelText);
            } else {
                console.error("生成失败:", progressData.error);
            }
        }
    }, 10000); // 每10秒查询一次
}

2. SSE的客户端实现

function startGenerationWithSSE(params) {
    const searchParams = new URLSearchParams(params);
    const source = new EventSource(`/api/3d-model/generate-sse?${searchParams}`);
    
    source.onmessage = (event) => {
        const data = JSON.parse(event.data);
        switch(data.type) {
            case "progress":
                console.log(`进度:${data.percentage}% | 状态:${data.status}`);
                break;
            case "complete":
                console.log("生成完成:", data.modelText);
                source.close();
                break;
            case "error":
                console.error("生成失败:", data.error);
                source.close();
                break;
        }
    };
    
    source.onerror = (err) => {
        console.error("SSE连接异常:", err);
        source.close();
    };
}

3. WebSocket的客户端实现

function startGenerationWithWebSocket(params) {
    const socket = new WebSocket(`ws://${window.location.host}/api/3d-model/generate-ws`);
    
    socket.onopen = () => {
        socket.send(JSON.stringify(params));
    };
    
    socket.onmessage = (event) => {
        const data = JSON.parse(event.data);
        switch(data.type) {
            case "progress":
                console.log(`进度:${data.percentage}% | 状态:${data.status}`);
                break;
            case "complete":
                console.log("生成完成:", data.modelText);
                socket.close();
                break;
            case "error":
                console.error("生成失败:", data.error);
                socket.close();
                break;
        }
    };
    
    socket.onerror = (err) => {
        console.error("WebSocket连接异常:", err);
        socket.close();
    };
}

四、方案选型建议

  • 优先选分阶段异步API:实现简单、兼容性强,无需处理长连接的异常情况,适合大多数场景。
  • 需要实时推送且无双向交互需求:选SSE,比WebSocket轻量,无需额外协议支持。
  • 需要客户端中途取消、调整参数等交互:选WebSocket,全双工通信更灵活。
  • 小型项目快速验证:选简单轮询,开发成本最低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 08:55:21