更新记录

1.0.0(2026-08-17) 下载此版本

  • 首次发布:跨端流式请求 UTS 插件。
  • 支持 Android / iOS / HarmonyOS / Web / 微信小程序 五端,兼容 uni-app 与 uni-app x。
  • 支持 SSE / Line / JSONL / Raw 四种协议。
  • 支持 GET / POST / PUT / PATCH / DELETE、自定义请求头与请求体。
  • 支持增量 UTF-8 解码(中文 / Emoji 跨分片不乱码)、Last-Event-ID 续传。
  • 支持自动重连(指数退避 / 抖动 / SSE retry / HTTP Retry-After / 状态码覆盖 / 累计预算)。
  • 支持网络与前后台恢复、高频回调批处理、业务终止帧。
  • 支持指标快照 getMetrics() 与脱敏诊断 exportDiagnostics()
  • 附带本地零依赖测试服务器与引擎逻辑 Node 验证脚本。

平台兼容性

uni-app(5.07)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - -

uni-app x(5.07)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - - -

lucis-sse 流式请求(SSE/Line/JSONL/Raw) UTS 插件

面向 AI 对话、智能客服、消息推送、日志流和长任务进度的跨端流式请求 UTS 插件。一次接入即可在 Android、iOS、HarmonyOS、Web、微信小程序 中统一处理 SSE、逐行文本、JSONL 和 Raw 文本流。

插件不是对 EventSource 的简单包装:支持 POST/PUT/PATCH/DELETE、自定义请求头与请求体、严格 UTF-8 增量解码、首包保护、SSE 标准字段、Last-Event-ID、可控重连、超时、限流与幂等取消。

部分功能未验证,如需在生产环境中使用,请自行测试。仅供有需求的开发者参考使用!!!

功能特性

  • 四种流协议sse / line / jsonl / raw,同一套回调处理不同服务端格式。
  • 不局限 GET:支持 GET / POST / PUT / PATCH / DELETE,可接 OpenAI 兼容接口、私有 AI 网关和业务流接口。
  • 两种请求头写法:兼容 headers 动态对象,同时推荐跨端更稳定的 headerList 强类型数组。
  • 首包不丢:所有回调在网络请求发出前完成注册,适配"连接后立即返回第一段"的服务端。
  • 完整 SSE 语义:支持 BOM、CR/LF/CRLF、注释心跳、多行 dataeventidretry 和未知字段忽略。
  • UTF-8 分片安全:五个平台统一使用自研增量解码器,保留不完整多字节尾部,中文与 Emoji 不会因网络分片乱码。
  • 断线续传:可将最近 id 自动写入下一次请求的 Last-Event-ID
  • 生产级重试:指数退避、抖动、SSE retry、HTTP Retry-After、状态码覆盖、累计时间预算和远端结束策略。
  • 网络与前后台恢复:自动感知网络变化,App 回到前台后可按策略恢复连接。
  • 连接指标getMetrics() 读取连接耗时、首字节、消息、字节、错误、重连次数。
  • 脱敏诊断exportDiagnostics() 生成可直接交给技术支持的 JSON 报告,不包含 URL 查询参数、请求头值、请求体或消息正文。
  • 高频批处理:按时间窗口或数量合并 chunk / message 回调,降低 AI 高频 token 对页面渲染的压力。
  • 业务终止帧:可识别 [DONE] 或自定义 data/event 控制帧,以正常完成原因结束。
  • 微信真实分块:使用 uni.request({ enableChunked: true }) + onChunkReceived,不是等待完整响应后伪装流式。
  • 无额外网络 SDK:Android 使用 HttpURLConnection,iOS 使用 URLSessionDataDelegate,HarmonyOS 使用 requestInStream,Web 使用 Fetch 流,微信使用 RequestTask。

支持平台

平台 是否支持 说明
uni-app Android HttpURLConnection;需要自定义基座
uni-app iOS URLSessionDataDelegate 原生流;需要自定义基座
uni-app HarmonyOS @ohos.net.http requestInStream 源码实现;需要自定义基座/HAP
uni-app Web Fetch 流;受 CORS 和代理缓冲影响,无需自定义基座
uni-app 微信小程序 enableChunked + onChunkReceived;需配置合法请求域名,无需自定义基座
uni-app x 各端 API 一致;小程序需 HBuilderX 5.07+
其他小程序 各平台分块 API 与发布限制不同,不伪造支持

安装与运行前准备

  1. 从 DCloud 插件市场导入插件,或把 uni_modules/lucis-sse 目录放入项目。
  2. 页面始终从插件根目录导入:import { connectStream } from '@/uni_modules/lucis-sse',不要指向 utssdk/index.uts
  3. Android / iOS / HarmonyOS 首次接入或升级原生代码后,需要重新制作自定义基座(只改页面、示例 URL 或普通业务代码时不需要)。
  4. Web 无需自定义基座,但服务端必须允许当前站点跨域访问并关闭响应缓冲。
  5. 微信小程序 无需自定义基座,但必须在微信公众平台配置 HTTPS 合法请求域名;正式版不能依赖开发工具的"忽略域名校验"。
  6. 生产接口建议使用 HTTPS,不要把 Token 写死在源码或日志中。

最小可运行示例

uni-app(Vue2/Vue3)

import { connectStream } from '@/uni_modules/lucis-sse'

const connection = connectStream({
  url: 'https://example.com/events',
  // 回调与参数一次性传入,插件会先注册回调再发起请求。
  onMessage(message) {
    console.log('收到完整事件:', message.data)
  },
  onError(error) {
    console.log('连接失败:', error.errCode, error.errMsg)
  },
  onComplete(event) {
    console.log('连接最终结束:', event.reason)
  }
})

// 页面离开或用户点击停止时调用;重复调用是安全的。
connection.abort()

uni-app x

import { connectStream, type StreamConnection, type StreamMessage, type StreamFail } from '@/uni_modules/lucis-sse'

let connection: StreamConnection | null = null

connection = connectStream({
  url: 'https://example.com/events',
  onMessage: (message: StreamMessage): void => {
    console.log('收到完整事件:' + message.data)
  },
  onError: (error: StreamFail): void => {
    console.log('连接失败:' + error.errCode.toString())
  },
  onComplete: (event): void => {
    console.log('连接最终结束:' + event.reason)
    connection = null
  }
})

微信小程序

import { connectStream } from '@/uni_modules/lucis-sse'

const connection = connectStream({
  // 必须提前配置为微信小程序合法请求域名。
  url: 'https://stream.example.com/events',
  protocol: 'sse',
  onMessage(message) {
    console.log('微信小程序收到事件:', message.data)
  },
  onComplete(event) {
    console.log('连接结束:', event.reason)
  }
})

// 页面卸载时主动取消,避免残留网络任务。
connection.abort()

API 列表

API 返回值 说明
connectStream(options) StreamConnection 创建流式连接,立即返回控制对象
closeAllStreams() void 幂等关闭本插件创建的全部连接
getStreamCapabilities() StreamCapabilities 获取当前平台真实能力矩阵
notifyStreamAppState(state) void 从 App.vue 通知前后台状态
notifyStreamNetworkChange(isConnected, networkType?) void 手动通知网络状态;通常无需调用

connectStream(options)

创建一个流式 HTTP 请求。函数同步返回连接控制对象,网络事件通过 options 中的回调持续返回。所有回调会在请求发出前保存,避免立即首包丢失。

参数 类型 必填 说明 默认值
options.url string HTTP/HTTPS 流地址
options.method StreamMethod HTTP 方法 GET
options.protocol StreamProtocol 解析协议 sse
options.headers UTSJSONObject 兼容 JS 普通对象的动态请求头
options.headerList Array\<StreamHeader> 推荐的强类型请求头;同名时覆盖 headers []
options.bodyText string 文本请求体,与 jsonBody 互斥
options.jsonBody any JSON 请求体,与 bodyText 互斥
options.connectTimeoutMs number 连接建立超时 30000
options.idleTimeoutMs number 打开后无字节到达超时,0 不限制 0
options.totalTimeoutMs number 单次连接总时长,0 不限制 0
options.lastEventId string 首次请求的 Last-Event-ID ''
options.maxBufferBytes number 未完成帧最大缓冲(按字符近似) 1048576
options.maxMessageBytes number 单条完整消息最大长度(按字符近似) 524288
options.reconnect StreamReconnectOptions 自动重连配置 { enabled: false }
options.recovery StreamRecoveryOptions 网络与前后台恢复策略 见下
options.batch StreamBatchOptions 高频回调批处理 { enabled: false }
options.terminal StreamTerminalOptions 业务终止帧策略 { enabled: false }
options.debug boolean 输出精简中文诊断日志 false
options.logPayload boolean debug 时打印业务文本,不建议生产开启 false
options.onOpen function HTTP 连接打开时触发
options.onChunk function 每个已解码文本分片触发
options.onChunkBatch function 批量文本分片;提供后接管 onChunk
options.onMessage function 每条完整协议消息触发
options.onMessageBatch function 批量完整消息;提供后接管 onMessage
options.onTerminal function 识别终止帧时触发,早于 onComplete
options.onRetry function 服务端 retry 更新或等待重连时触发
options.onStateChange function 连接状态变化时触发
options.onEnvironmentChange function 网络或 App 前后台变化时触发
options.onError function 单次失败或最终失败时触发
options.onComplete function 连接最终结束时只触发一次
options.success / fail / complete function 兼容 uni 风格,与对应回调同时触发

重连参数 reconnect

参数 类型 说明 默认值
reconnect.enabled boolean 是否自动重连 false
reconnect.maxAttempts number 最大重连次数 3
reconnect.initialDelayMs number 初始等待毫秒数 1000
reconnect.maxDelayMs number 最大等待毫秒数 30000
reconnect.multiplier number 指数退避倍数 2
reconnect.jitterRatio number 随机抖动比例(0 到 1) 0.2
reconnect.useServerRetry boolean 是否采用 SSE retry 字段 true
reconnect.policy StreamRetryPolicyOptions Retry-After、状态码、预算等

生产级重试 reconnect.policy

参数 类型 说明 默认值
policy.respectRetryAfter boolean 是否采用 HTTP Retry-After false
policy.maxRetryAfterMs number Retry-After 最大贡献等待时间 60000
policy.maxElapsedMs number 单个重试周期累计时间预算;0 不限制 0
policy.retryableStatusCodes Array\<number> 额外允许重试的 HTTP 状态码 []
policy.nonRetryableStatusCodes Array\<number> 明确禁止重试的状态码;冲突时优先 []
policy.remoteEnd string 远端正常结束后的重连策略 always

自动等待优先级:有效 HTTP Retry-After → SSE retry: → 客户端指数退避POST 默认关闭自动重连,除非服务端提供幂等键并允许安全重放。

返回值 StreamConnection

字段 类型 说明
getId() () => string 返回本次连接 ID
getState() () => string 返回当前状态(idle/connecting/open/reconnect-wait/closed)
getMetrics() () => StreamMetrics 返回当前连接指标快照
exportDiagnostics() () => string 导出脱敏 JSON 诊断报告
reconnect(reason?) (reason?: string) => boolean 请求立即恢复连接
abort(reason?) (reason?: string) => void 幂等取消连接

常见用法

POST + 自定义请求头 + 鉴权

import { connectStream } from '@/uni_modules/lucis-sse'

const connection = connectStream({
  url: 'https://api.example.com/v1/chat/stream',
  method: 'POST',
  protocol: 'sse',
  headerList: [
    { name: 'Authorization', value: 'Bearer ' + runtimeToken },
    { name: 'X-Customer-ID', value: customerId }
  ],
  jsonBody: {
    model: 'your-model',
    messages: [{ role: 'user', content: '你好' }],
    stream: true
  },
  reconnect: { enabled: false },
  terminal: { enabled: true, deliverMessage: false },
  onMessage: (message) => console.log(message.data),
  onTerminal: (event) => console.log('服务端业务完成:' + event.source),
  onError: (error) => console.log(error.errCode + ':' + error.errMsg)
})

自动重连 + Last-Event-ID

const connection = connectStream({
  url: 'https://example.com/events',
  protocol: 'sse',
  reconnect: {
    enabled: true,
    maxAttempts: 5,
    initialDelayMs: 1000,
    maxDelayMs: 15000,
    multiplier: 2,
    jitterRatio: 0.2,
    useServerRetry: true
  },
  onRetry: (event) => {
    console.log('第 ' + event.attempt + ' 次重连将在 ' + event.delayMs + 'ms 后执行')
  },
  onMessage: (message) => {
    // 插件会保存 SSE id,并在重连时自动发送 Last-Event-ID。
    console.log(message.id + ': ' + message.data)
  }
})

App 前后台恢复

// App.vue
import { notifyStreamAppState } from '@/uni_modules/lucis-sse'

export default {
  onShow() {
    notifyStreamAppState('foreground')
  },
  onHide() {
    notifyStreamAppState('background')
  }
}

指标与脱敏诊断

const metrics = connection.getMetrics()
console.log('连接耗时:' + metrics.connectDurationMs + 'ms')
console.log('首字节:' + metrics.firstByteDurationMs + 'ms')

// 报告不包含 Authorization/Cookie 值、URL 查询参数、body、chunk 或 message.data。
const diagnosticJson = connection.exportDiagnostics()

回调数据

StreamMessage

字段 类型 说明
connectionId string 连接 ID
protocol string 当前解析协议
data string 完整文本消息
event string SSE event;缺省为 message,非 SSE 为空
id string 最近一次有效 SSE id
json any | null JSONL 解析结果;其他协议为 null
sequence number 消息序号,从 1 开始

StreamCompleteEvent

字段 类型 说明
reason string remote-end / terminal-message / abort / error / timeout / reconnect-exhausted / retry-budget-exhausted
manuallyAborted boolean 是否主动取消
statusCode number 最终 HTTP 状态码
reconnectCount number 实际重连次数
lastEventId string 最后 SSE 事件 ID

错误码

错误码 含义
9098001 参数不合法
9098002 平台不支持
9098003 网络连接失败
9098004 连接建立超时
9098005 连接空闲超时
9098006 连接总时长超时
9098007 HTTP 状态异常
9098008 响应流读取失败
9098009 UTF-8 解码失败
9098010 协议解析失败
9098011 JSONL 无效
9098012 缓冲区超限
9098013 消息超限
9098014 重连耗尽
9098015 重试预算耗尽

各平台注意事项

  • Android:需要 android.permission.INTERNET(插件 Manifest 已声明);首次接入必须制作自定义基座。Thread SAM、ByteArray↔Uint8ArrayString.toByteArray() 三个点在打基座时需验证。
  • iOS:需要 macOS + Xcode;云端打包或自定义基座。UTS↔Swift 的闭包回调、[UInt8]↔Array<number>Map↔Dictionary 在打基座时需验证。
  • HarmonyOS:需 DevEco 与自定义基座/HAP;不依赖加密 module.har。
  • Web:服务端必须配置 CORS,代理层不能缓冲响应(建议返回 X-Accel-Buffering: no)。
  • 微信小程序:基础库 ≥ 2.20.1;必须配置 HTTPS 合法请求域名;abort() 在 enableChunked 下可能失效,插件会按连接自然结束兜底。

本地测试服务

仓库自带零依赖 Node 本地测试服务,覆盖 SSE 基础、中文跨分片、POST 回显、Line/JSONL/Raw、断线续传、Retry-After、终止帧、断流等场景:

# 在项目根目录执行;服务默认监听 0.0.0.0:8787,允许局域网真机访问
node uni_modules/lucis-sse/example/server/lucis-sse-test-server.js
运行环境 示例地址 说明
Web / 同一台电脑 http://127.0.0.1:8787 浏览器与测试服务运行在同一台电脑
Android 模拟器 http://10.0.2.2:8787 Android Studio 模拟器访问宿主机默认映射
Android/iOS/HarmonyOS 真机 http://\<电脑局域网IPv4>:8787 手机和电脑需在同一网络,防火墙放行 8787
微信开发者工具 已备案的 HTTPS 测试域名 本地 HTTP 只适合临时开发调试

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android 仅需 android.permission.INTERNET;iOS、HarmonyOS 与 Web 使用系统网络能力;微信小程序需在平台后台配置合法请求域名

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

仅访问客户传入的流式接口地址并发送客户显式配置的请求头和请求体;插件不采集、不上传、不保存账号、Token 或业务消息

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议