如何解析XMLHttpRequest响应并获取SSE最后推送值?
问题:如何从SSE推送的全量响应中提取最后一条数据
我有一个返回SseEmitter的Web服务,用于实现加载进度条,当前使用以下XMLHttpRequest方法接收推送:
static async synchronize(component: Vue) { let xhr = new XMLHttpRequest(); xhr.open('PATCH', 'myUrl.com'); xhr.responseType = "text" xhr.setRequestHeader('Authorization', 'mySessionToken') xhr.setRequestHeader("Content-Type", "text/event-stream") xhr.onload = function () { if (this.status >= 200 && this.status < 300) { resolve(xhr.response) } else { reject({status: this.status, statusText: xhr.statusText}) } } xhr.onerror = function () {reject({status: this.status, statusText: xhr.statusText})} xhr.onreadystatechange = function() {if (xhr.readyState == XMLHttpRequest.DONE) { alert(xhr.responseText) }} xhr.onprogress = function(onEvent) { console.log(xhr.response) } xhr.send() }
目前该方法可运行,但xhr.response返回包含所有历史推送内容的字符串,格式如下:
data:"{ hello: '1' }" data:"{ hello: '2' }" ... //以此类推直到100
每次推送事件触发时,响应会返回全部历史状态记录,内容随推送次数增加而变大。尝试使用JSON.parse解析时报错,推测是响应格式不符合JSON规范。请问是否有办法仅获取该响应中的最后一条推送值?
解决方案
方法1:优化XMLHttpRequest的响应处理
针对当前XHR返回的全量数据,通过字符串分割提取最后一条推送,并修正JSON格式后解析:
修改onprogress事件处理逻辑:
xhr.onprogress = function(onEvent) { const fullResponse = xhr.response; if (!fullResponse) return; // 1. 按换行分割所有推送记录,过滤空行 const lines = fullResponse.split('\n').filter(line => line.trim() !== ''); if (lines.length === 0) return; // 2. 获取最后一条推送记录 const lastLine = lines[lines.length - 1]; // 3. 提取并修正JSON格式:去掉data前缀、替换单引号为双引号 const jsonStr = lastLine .replace(/^data:"/, '') // 移除开头的data:" .replace(/"$/, '') // 移除结尾的" .replace(/'/g, '"'); // 替换单引号为标准JSON双引号 // 4. 解析JSON并使用 try { const latestData = JSON.parse(jsonStr); console.log('最新进度:', latestData.hello); // 直接更新Vue组件的进度条状态 component.progress = latestData.hello; } catch (error) { console.error('解析推送数据失败:', error); } }
方法2:使用原生EventSource API(更推荐)
EventSource是浏览器原生支持SSE的API,会自动逐条接收推送,无需处理全量历史数据,代码更简洁:
static async synchronize(component: Vue) { // 注意:部分浏览器可能不支持EventSource设置PATCH方法,需提前确认兼容性 const eventSource = new EventSource('myUrl.com', { headers: { 'Authorization': 'mySessionToken', 'Content-Type': 'text/event-stream' }, method: 'PATCH' }); // 接收每条推送 eventSource.onmessage = function(event) { try { // 修正单引号为双引号后解析 const latestData = JSON.parse(event.data.replace(/'/g, '"')); console.log('最新进度:', latestData.hello); // 更新组件进度 component.progress = latestData.hello; // 进度到100时关闭连接 if (latestData.hello === '100') { eventSource.close(); } } catch (error) { console.error('解析推送数据失败:', error); } }; // 处理连接错误 eventSource.onerror = function(error) { console.error('SSE连接错误:', error); eventSource.close(); // 触发错误回调逻辑 // reject({status: error.status, statusText: error.message}); }; }
内容的提问来源于stack exchange,提问作者user17196717
相关产品推荐
相关产品推荐

