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

Django流式返回数据后JS无法正常更新HTML,仅输出‘2’求排查

问题:Django流式返回数据,JS仅触发第二个条件(控制台输出‘2’)

我想用JavaScript接收Django后端的流式数据,根据不同状态码更新HTML元素内容,但目前JS只在控制台输出‘2’,后续步骤完全没触发,求排查问题。

Django视图代码

import time
from django.http import StreamingHttpResponse
from django.shortcuts import render

def message(msg):
    time.sleep(1)
    return f'{msg} '

def get_data():
    status_code =['AB','CD','EF','GH','IJ']
    for i in status_code:
        time.sleep(0.5)
        print(i)
        yield message(i)

def test_stream(request):
    stream = get_data()
    response = StreamingHttpResponse(stream, status=200, content_type='text/event-stream')
    response['Cache-Control'] = 'no-cache'
    return response

def jobs(request):
    return render(request, 'jobs/index.html')

HTML中的JavaScript代码(片段)

// 注:原代码缺少请求监听的完整逻辑,以下为用户提供的处理片段
const arr = oEvent.target.responseText.split(' ')
log(arr.reverse()[1])
const data = arr.reverse()[1]
if (data == 'AB'){
    document.getElementById('step1_status').innerHTML = '시작';
    log('1')
}
else if (data == 'CD'){
    document.getElementById('step1_status').innerHTML = '완료';
    document.getElementById('step2_status').innerHTML = '시작';
    log('2')
}
else if (data == 'EF'){
    document.getElementById('step2_status').innerHTML = '완료';
    document.getElementById('step3_status').innerHTML = '시작';
    log('3')
}
else if (data == 'GH'){
    document.getElementById('step3_status').innerHTML = '완료';
    document.getElementById('step4_status').innerHTML = '시작';
    log('4')
}
else if (data == 'IJ'){
    document.getElementById('step4_status').innerHTML = '완료';
    log('5')
}
}

浏览器控制台截图

控制台截图


问题原因分析

  1. SSE格式不规范:你设置了content_type='text/event-stream',但后端返回的内容不符合Server-Sent Events(SSE)的标准格式。SSE要求每条消息必须以data: 内容\n\n的格式返回,而你现在直接返回AB 、CD 这类字符串,浏览器无法识别独立的消息,只会把所有返回内容累积成一个字符串。

  2. JS处理逻辑错误:如果用普通XMLHttpRequest的onload事件,它只会在整个流式请求完成后触发一次,此时responseText是所有后端返回内容的拼接(比如AB CD EF GH IJ )。你通过split(' ').reverse()[1]取到的是CD,因此只会触发第二个条件,输出‘2’,后续状态码根本没机会被单独处理。

解决方案

1. 修复Django视图的SSE格式

修改message函数,返回符合SSE规范的内容:

def message(msg):
    time.sleep(1)
    # 遵循SSE格式:data: 内容 + 换行 + 换行
    return f'data: {msg}\n\n'

2. 用EventSource API处理SSE(推荐)

替换原JS代码,使用专门的SSE API来监听流式消息,每条后端返回的消息都会触发一次onmessage事件:

// 连接到后端的test_stream路由,注意路径要和你的URL配置一致
const eventSource = new EventSource('/test_stream/');

eventSource.onmessage = function(e) {
    const data = e.data.trim(); // 去除多余空格,拿到状态码
    console.log(data);

    if (data === 'AB') {
        document.getElementById('step1_status').innerHTML = '시작';
        console.log('1');
    } else if (data === 'CD') {
        document.getElementById('step1_status').innerHTML = '완료';
        document.getElementById('step2_status').innerHTML = '시작';
        console.log('2');
    } else if (data === 'EF') {
        document.getElementById('step2_status').innerHTML = '완료';
        document.getElementById('step3_status').innerHTML = '시작';
        console.log('3');
    } else if (data === 'GH') {
        document.getElementById('step3_status').innerHTML = '완료';
        document.getElementById('step4_status').innerHTML = '시작';
        console.log('4');
    } else if (data === 'IJ') {
        document.getElementById('step4_status').innerHTML = '완료';
        console.log('5');
        eventSource.close(); // 所有步骤完成后关闭连接
    }
};

// 处理连接错误
eventSource.onerror = function(e) {
    console.error('SSE连接异常:', e);
    eventSource.close();
};

3. 额外注意事项

  • 确保Django的URL配置中,/test_stream/正确映射到test_stream视图。
  • 如果你坚持用XMLHttpRequest,需要监听onprogress事件,每次读取新增的响应内容,而不是等待整个请求完成再处理。但EventSource是SSE场景下更简洁的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 22:39:53