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

如何用jQuery/FastAPI实现并行异步调用,互不等待?

问题解决:FastAPI+jQuery聊天应用实现非阻塞后台任务

核心问题分析

当前代码的阻塞根源在后端:

  • /side_track接口使用了同步的time.sleep(10),会直接阻塞FastAPI的异步事件循环,导致所有后续请求(包括/submit_message)都必须等待10秒才能处理。
  • 前端即使不等待side_track的响应,后端的事件循环阻塞依然会让主请求变慢。

解决方案

第一步:修复后端阻塞问题

方案A:异步化IO操作(适合可异步的耗时任务)

将同步的time.sleep替换为异步的asyncio.sleep,避免阻塞事件循环:

@app.post("/side_track")
async def side_track(message_data: MessageInput):
    import asyncio
    await asyncio.sleep(10)  # 异步sleep不阻塞事件循环
    return {"status": "ok"}

方案B:使用BackgroundTasks(适合无法异步化的同步任务)

如果实际场景是CPU密集型或无法异步的操作(比如旧版同步数据库查询),用FastAPI的BackgroundTasks将任务放到后台执行,接口立即返回:

from fastapi import BackgroundTasks

# 定义耗时的同步任务
def long_running_task(message: str):
    import time
    time.sleep(10)
    print(f"后台任务完成:{message}")

@app.post("/side_track")
async def side_track(message_data: MessageInput, background_tasks: BackgroundTasks):
    # 将任务添加到后台
    background_tasks.add_task(long_running_task, message_data.message)
    # 立即返回响应,不等待任务完成
    return {"status": "任务已提交至后台处理"}

第二步:前端优化(确保主流程不等待后台任务)

调整前端代码,让side_track在后台独立执行,不影响主请求的响应速度:

$(document).ready(function () {
    $('#message-form').submit(async function (event) {
        event.preventDefault();

        const input_message = $('#message-form input[name=message]').val();
        $('#message-list').append(`<li><strong>${input_message}</strong></li>`);

        // 调用后台任务,不等待结果,直接进入主请求流程
        side_track(input_message);

        // 立即处理主请求
        try {
            const response = await fetch('/submit_message', {
                method: 'POST',
                body: JSON.stringify({ message: input_message }),
                headers: { 'Content-Type': 'application/json' },
            });
            const data = await response.json();
            
            $('#message-form')[0].reset();
            $('#message-list').append(`<li>${data.message}</li>`);
        } catch (err) {
            console.error('主请求失败:', err);
            $('#message-list').append('<li><em>请求出错,请重试</em></li>');
        }
    });
});

// 后台任务处理函数,独立执行
async function side_track(question) {
    try {
        const response = await fetch('/side_track', {
            method: 'POST',
            body: JSON.stringify({ message: question }),
            headers: { 'Content-Type': 'application/json' },
        });
        const result = await response.json();
        // 可选:任务完成后通知用户
        $('#message-list').append(`<li><em>后台任务状态:${result.status}</em></li>`);
    } catch (err) {
        console.error('后台任务失败:', err);
    }
}

额外优化:修复submit_message的流式响应逻辑

如果需要保持流式返回随机数,调整后端代码使用StreamingResponse:

from fastapi.responses import StreamingResponse
import asyncio
import random
import json

async def random_numbers_stream():
    while True:
        yield f"{json.dumps({'message': random.randint(1,10)})}\n"
        await asyncio.sleep(0.1)

@app.post("/submit_message")
async def submit_message(message_data: MessageInput):
    return StreamingResponse(random_numbers_stream(), media_type="application/jsonlines")

对应的前端读取逻辑也要调整为逐行读取:

// 替换主请求中的处理逻辑
const response = await fetch('/submit_message', {
    method: 'POST',
    body: JSON.stringify({ message: input_message }),
    headers: { 'Content-Type': 'application/json' },
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
const newMessage = document.createElement('li');
$('#message-list').append(newMessage);

while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    const data = JSON.parse(decoder.decode(value));
    newMessage.innerHTML = `实时随机数:${data.message}`;
}

最终效果

用户提交消息后:

  1. 立即显示自己的输入内容
  2. 主请求/submit_message的结果(或流式数据)会实时显示
  3. 后台任务/side_track在服务器端独立执行,完成后可选择性通知用户

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 09:57:43