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') } }
浏览器控制台截图

问题原因分析
SSE格式不规范:你设置了
content_type='text/event-stream',但后端返回的内容不符合Server-Sent Events(SSE)的标准格式。SSE要求每条消息必须以data: 内容\n\n的格式返回,而你现在直接返回AB、CD这类字符串,浏览器无法识别独立的消息,只会把所有返回内容累积成一个字符串。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
相关产品推荐
相关产品推荐

