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

前端JS通过AJAX订阅Chunked数据接口,如何仅解析delta新增数据?

这问题我之前碰到过,其实核心就是抓住Chunked传输的分块特性,区分两种常见场景来处理就行,给你几个实用的实现思路:

核心思路概述

Chunked传输的本质是服务器把数据拆成多个小块逐步发送,前端可以通过流API(比如Fetch的ReadableStream)实时捕获每个新到达的块。你现在的问题是之前把所有块拼起来处理,所以显示累积内容;要拿到delta,要么直接处理每个新块(如果服务器发的就是增量),要么对比前后内容的差异提取新增部分。

场景1:服务器分块发送纯增量内容(最理想情况)

如果服务器本身就是每次发送新增的内容片段(比如实时日志、事件流),那直接读取每个chunk处理即可,完全不需要累积。用Fetch API实现的话,代码大概是这样:

async function streamDeltaEvents(url) {
  const response = await fetch(url);
  // 获取流读取器
  const reader = response.body.getReader();
  // 用于把二进制chunk转成文本,处理多字节字符
  const textDecoder = new TextDecoder();

  while (true) {
    // 读取下一个chunk
    const { done, value } = await reader.read();
    if (done) break; // 流结束,退出循环

    // 把二进制chunk解码成文本,stream: true确保跨chunk的多字节字符不被截断
    const deltaContent = textDecoder.decode(value, { stream: true });
    
    // 这里写你的解析逻辑,比如解析事件数据
    handleNewDelta(deltaContent);
  }
}

// 自定义的增量处理函数
function handleNewDelta(delta) {
  console.log('刚收到的新增内容:', delta);
  // 比如解析成JSON、更新UI等操作
}
场景2:服务器返回的是累积式完整内容(需要手动提取delta)

有些服务器可能会在每个chunk里返回从开始到当前的全部内容(比如某些实时更新的状态接口),这时候就需要记录上次处理到的位置,每次截取新增部分:

async function extractDeltaFromCumulativeStream(url) {
  const response = await fetch(url);
  const reader = response.body.getReader();
  const textDecoder = new TextDecoder();
  let lastProcessedLength = 0; // 记录上次处理完的内容长度

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const fullContent = textDecoder.decode(value, { stream: true });
    // 截取从上次位置到当前的新增部分
    const deltaContent = fullContent.slice(lastProcessedLength);
    
    handleNewDelta(deltaContent);
    // 更新上次处理的长度
    lastProcessedLength = fullContent.length;
  }
}
进阶:处理结构化增量数据(如JSON事件)

如果你的事件是JSON格式,推荐服务器用**NDJSON(换行分隔JSON)**传输,这样每个chunk里的内容可以按行分割,处理完整的JSON对象,避免跨chunk的不完整JSON:

async function streamNDJSONEvents(url) {
  const response = await fetch(url);
  const reader = response.body.getReader();
  const textDecoder = new TextDecoder();
  let buffer = ''; // 缓存不完整的行(比如chunk末尾的半行JSON)

  while (true) {
    const { done, value } = await reader.read();
    if (done) {
      // 处理最后剩下的缓存内容
      if (buffer.trim()) {
        const event = JSON.parse(buffer);
        handleNewEvent(event);
      }
      break;
    }

    buffer += textDecoder.decode(value, { stream: true });
    // 按换行分割内容
    const lines = buffer.split('\n');
    // 把最后一行(可能不完整)放回缓存
    buffer = lines.pop();

    // 处理每一行完整的JSON事件
    for (const line of lines) {
      if (line.trim()) {
        const event = JSON.parse(line);
        handleNewEvent(event);
      }
    }
  }
}

function handleNewEvent(event) {
  console.log('刚收到的新增事件:', event);
  // 比如更新页面数据、触发前端事件等
}
关键注意事项
  • 一定要用TextDecoder的stream: true参数,否则跨chunk的多字节字符(比如中文、emoji)会被截断乱码。
  • 如果用XMLHttpRequest而不是Fetch,监听onprogress事件,从xhr.response中截取新增部分(思路和场景2一致),不过Fetch的Stream API更现代简洁。
  • 测试时可以用浏览器的Network面板查看每个chunk的内容,确认服务器是发增量还是累积内容,再选择对应的处理方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:08:06