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

如何更新Python Flask应用,实现循环内逐次向JavaScript发送信息

实现逐次推送选秀结果的解决方案

要实现逐个发送选秀结果并允许用户交互,你需要用**服务器发送事件(SSE)**结合Flask的流式响应能力,同时配合前端处理用户输入后继续流程。以下是具体实现:

Flask 后端代码

from flask import Flask, request, jsonify, session, Response
import json

app = Flask(__name__)
app.secret_key = "your-secret-key-here"  # 必须设置才能使用session存储进度

# 模拟获取选秀顺位列表(实际可从前端请求或数据库读取)
def get_draft_order():
    return [(1, "Team A"), (2, "User Team"), (3, "Team B"), (4, "Team C")]

# 模拟AI自动选秀逻辑
def simulate_ai_pick(team, pick_num):
    return {
        "pick_number": pick_num,
        "team": team,
        "player": f"AI选中球员-{team}-{pick_num}"
    }

@app.route("/simulate-draft", methods=["POST"])
def simulate_draft():
    user_team = request.json.get("user_team")
    draft_order = get_draft_order()
    
    # 初始化session存储选秀进度和结果
    if "draft_progress" not in session:
        session["draft_progress"] = 0
        session["user_team"] = user_team
        session["draft_results"] = []

    def generate_stream():
        while session["draft_progress"] < len(draft_order):
            pick_num, current_team = draft_order[session["draft_progress"]]
            
            if current_team == user_team:
                # 推送"等待用户选择"的信号给前端
                yield f'data: {json.dumps({"type": "user_turn", "pick_number": pick_num, "team": current_team})}\n\n'
                break  # 暂停循环,等待用户提交选择
            
            # AI自动选秀,推送结果
            ai_pick = simulate_ai_pick(current_team, pick_num)
            session["draft_results"].append(ai_pick)
            yield f'data: {json.dumps({"type": "ai_pick", "data": ai_pick})}\n\n'
            
            session["draft_progress"] += 1
        
        # 所有顺位处理完成,推送结束信号
        if session["draft_progress"] >= len(draft_order):
            yield f'data: {json.dumps({"type": "done", "results": session["draft_results"]})}\n\n'
            # 清空session数据
            session.pop("draft_progress", None)
            session.pop("user_team", None)
            session.pop("draft_results", None)

    return Response(generate_stream(), mimetype="text/event-stream")

# 接收用户提交的选秀选择
@app.route("/submit-user-pick", methods=["POST"])
def submit_user_pick():
    user_pick_data = request.json
    user_team = session.get("user_team")
    
    # 将用户选择加入结果列表
    session["draft_results"].append({
        "pick_number": user_pick_data["pick_number"],
        "team": user_team,
        "player": user_pick_data["player"]
    })
    session["draft_progress"] += 1  # 更新进度
    
    return jsonify({"status": "success"})

JavaScript 前端代码

<!-- 假设页面上有这些元素 -->
<div>
    <input type="text" id="user-team" placeholder="输入你的队伍名称">
    <button onclick="startDraft()">开始选秀</button>
</div>
<div id="draft-results"></div>

<!-- 用户选择弹窗 -->
<div id="user-pick-modal" style="display: none;">
    <h3>轮到你选择了!第<span id="current-pick-num"></span>顺位</h3>
    <input type="text" id="player-name" placeholder="输入选中球员名称">
    <button onclick="submitUserPick()">确认选择</button>
</div>

<script>
let currentEventSource;
let currentPickNum;

// 启动选秀模拟
function startDraft() {
    const userTeam = document.getElementById("user-team").value.trim();
    if (!userTeam) return alert("请输入你的队伍名称");

    // 创建SSE连接接收流式推送
    currentEventSource = new EventSource("/simulate-draft", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ user_team: userTeam })
    });

    currentEventSource.onmessage = function(event) {
        const data = JSON.parse(event.data);
        switch (data.type) {
            case "ai_pick":
                displayPick(data.data);
                break;
            case "user_turn":
                currentEventSource.close();
                showUserPickModal(data.pick_number);
                break;
            case "done":
                currentEventSource.close();
                displayFinalResults(data.results);
                break;
        }
    };

    currentEventSource.onerror = function(error) {
        console.error("选秀模拟出错:", error);
        currentEventSource.close();
    };
}

// 显示单条选秀结果
function displayPick(pickData) {
    const resultsDiv = document.getElementById("draft-results");
    const pickElement = document.createElement("div");
    pickElement.textContent = `第${pickData.pick_number}顺位:${pickData.team} 选择了 ${pickData.player}`;
    resultsDiv.appendChild(pickElement);
}

// 显示用户选择弹窗
function showUserPickModal(pickNum) {
    currentPickNum = pickNum;
    document.getElementById("current-pick-num").textContent = pickNum;
    document.getElementById("user-pick-modal").style.display = "block";
}

// 提交用户选择并继续选秀
function submitUserPick() {
    const playerName = document.getElementById("player-name").value.trim();
    if (!playerName) return alert("请输入球员名称");

    fetch("/submit-user-pick", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
            pick_number: currentPickNum,
            player: playerName
        })
    })
    .then(res => res.json())
    .then(data => {
        if (data.status === "success") {
            document.getElementById("user-pick-modal").style.display = "none";
            document.getElementById("player-name").value = "";
            // 重新启动选秀流程,继续剩余顺位
            startDraft();
        }
    });
}

// 显示最终选秀结果
function displayFinalResults(results) {
    const resultsDiv = document.getElementById("draft-results");
    resultsDiv.innerHTML += "<h3>选秀完成!最终结果:</h3>";
    results.forEach(pick => {
        const pickElement = document.createElement("div");
        pickElement.textContent = `第${pick.pick_number}顺位:${pick.team} 选择了 ${pick.player}`;
        resultsDiv.appendChild(pickElement);
    });
}
</script>

关键说明

  1. 流式响应与SSE:Flask通过Response包裹生成器函数,设置text/event-stream类型实现服务器主动推送;前端用EventSource原生接收流式消息,无需手动处理分块。
  2. 进度存储:用Flask的session存储当前选秀进度、用户队伍和已选结果,避免多用户流程冲突(生产环境可替换为数据库)。
  3. 用户交互暂停:遇到用户队伍时,后端推送user_turn信号,前端关闭当前SSE连接,弹出输入框;用户提交选择后,后端更新进度,前端重新启动选秀流程继续剩余顺位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 16:17:07