sse.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /**
  2. * SSE 流式接收工具(支持多事件类型)
  3. * 适用于 uni-app 微信小程序
  4. *
  5. * 事件类型:
  6. * intent — 意图分类
  7. * status — 思考状态
  8. * content — 回答内容(默认)
  9. * meta — 元数据(来源、conversation_id)
  10. */
  11. export function createSSE(url, data, options = {}) {
  12. const {
  13. headers = {},
  14. onMessage = () => {},
  15. onDone = () => {},
  16. onError = () => {},
  17. onIntent = () => {},
  18. onStatus = () => {},
  19. onMeta = () => {}
  20. } = options
  21. let buffer = ''
  22. let aborted = false
  23. let currentEvent = ''
  24. const defaultHeaders = {
  25. 'Content-Type': 'application/json',
  26. 'Accept': 'text/event-stream',
  27. }
  28. const token = uni.getStorageSync('access_token')
  29. if (token) {
  30. defaultHeaders['Authorization'] = 'Bearer ' + token
  31. }
  32. const task = uni.request({
  33. url,
  34. method: 'POST',
  35. data,
  36. header: { ...defaultHeaders, ...headers },
  37. enableChunked: true,
  38. responseType: 'text',
  39. success: () => { if (!aborted) onDone() },
  40. fail: (err) => { if (!aborted) onError(err) }
  41. })
  42. task.onChunkReceived((res) => {
  43. if (aborted) return
  44. try {
  45. const chunk = typeof res.data === 'string'
  46. ? res.data
  47. : new TextDecoder('utf-8').decode(res.data)
  48. buffer += chunk
  49. const lines = buffer.split('\n')
  50. buffer = lines.pop() || ''
  51. for (const line of lines) {
  52. if (line.startsWith('event: ')) {
  53. currentEvent = line.slice(7).trim()
  54. continue
  55. }
  56. if (!line.startsWith('data: ')) continue
  57. const d = line.slice(6)
  58. if (d === '[DONE]') { onDone(); return }
  59. if (currentEvent === 'intent') {
  60. onIntent(d)
  61. } else if (currentEvent === 'status') {
  62. onStatus(d)
  63. } else if (currentEvent === 'meta') {
  64. try { onMeta(JSON.parse(d)) } catch(e) {}
  65. } else {
  66. // content 或默认
  67. onMessage(d)
  68. }
  69. currentEvent = ''
  70. }
  71. } catch (e) {
  72. console.error('[SSE] Parse error:', e)
  73. }
  74. })
  75. return {
  76. abort: () => {
  77. aborted = true
  78. task.abort()
  79. }
  80. }
  81. }
  82. export default { createSSE }