收藏
回答

wx小程序端对SSE的长连接会出现偶发性连接超时失败回调,该怎么才能保证长连接的稳定?

目前总会报异常信息:{"errMsg": "request:fail errcode:-7 cronet_error_code:-7 error_msg:net::ERR_TIMED_OUT", "errno": 600001}
(in promise) MiniProgramError
{"errMsg":"uploadFile:fail errcode:-101 cronet_error_code:-101 error_msg:net::ERR_CONNECTION_RESET","errno":600001}
Object

正常数据,不会触发:{"event": "answer", "id": "10", "data": "{"connectionId":"sse-conversation-prefix-2007699858181459968-1767507922112","conversationId":"2004510190640173056","content":""}"}
触发场景:空Event 数据格式:{"id": "11", "data": "{"connectionId":"sse-conversation-prefix-2007699858181459968-1767507922112","conversationId":"2004510190640173056","content":""}"}
但空Event数据这种场景也不是100% 会触发,偶尔会触发失败回调,就肯奇怪,所以排查不出真正的问题在哪里?
问微信助手说,是wx底层可能会对非活跃的长连接进行回收,但这个回收策略咱也不清楚,目前 15秒发送一个 空Event数据,作为心跳包给到前端。但还是会出现触发失败回调。
请问,wx端对SSE 的长连接出现这种情况有没有处理经验,该怎么才能保证长连接的稳定?

export function requesSendsse(data = {}, settings, callback = null) {
  const getOptions = {
    isToken: true,
    showLoading: true,
    showErrorMsg: true,
    ...settings
  }
  if (getOptions.showLoading) {
    loading()
  }
  //基础配置信息
  var baseConfig = () => {
    const headers = {
      baseUrl: configUrl.API_URL,
      timeout: getOptions.timeout || 1000 * 60 * 3
    }
    if (data.baseUrl) {
      headers.baseUrl = data.baseUrl
    }
    headers.headers = {
      'Content-Type': data.dataType == 'form' ? 'application/x-www-form-urlencoded;charset=utf-8' : 'application/json;charset=utf-8'
    }
    if (getOptions.isToken) {
      headers.headers.token = uni.getStorageSync('token') || ''
    }
    return headers
  }
  var options = Object.assign(baseConfig(), data)
  return new Promise((resolve, reject) => {
    // 用于累积分块数据
    let buffer = ''
    let requestTask = uni.request({
      url: `${options.baseUrl}${options.url}`,
      enableChunked: true, //微信小程序支持SSE
      method: options.method || 'POST',
      data: options.data || {},
      header: options.headers,
      timeout: options.timeout,
      success(res) {
        console.log('SSE连接关闭')
        reject()
      },
      fail(error) {
        console.log('sse请求失败')
        console.log(error)
        if (getOptions.showLoading) {
          hideLoading()
        }
        if (getOptions.showErrorMsg) {
          setTimeout(() => {
            toast((error && error.statusText) || 'SSE连接到服务器失败')
          }, 200)
        }
        reject(error)
      }
    })
    requestTask.onHeadersReceived((res) => {
      console.log('SSE连接已建立,状态码:', res.statusCode)
      if (configUrl.envVersion != 'develop') {
        console.log(`请求参数${options.baseUrl}${data.url}\n${JSON.stringify(data.data, null, '\t')}\n`)
        console.log('请求成功\n' + JSON.stringify(res.data))
      }
    })
    requestTask.onChunkReceived((res) => {
      try {
        // 将ArrayBuffer转换为文本
        const uint8Array = new Uint8Array(res.data)
        let text = ''

        // 优先使用全局 TextDecoder
        if (typeof TextDecoder === 'function') {
          text = new TextDecoder('utf-8').decode(uint8Array)
        } else {
          text = utf8ArrayToString(uint8Array)
        }
        // 累积数据到缓冲区
        buffer += text
        // 按双换行符分割完整的SSE事件
        const events = buffer.split('\n\n')
        // 保留最后一个可能不完整的事件
        buffer = events.pop() || ''
        // 处理完整的事件
        events.forEach((eventText) => {
          if (eventText.trim()) {
            const lines = eventText.split('\n')
            //console.log('完整事件:', lines)

            let eventData = {}
            lines.forEach((line) => {
              if (line.startsWith('event:')) {
                eventData.event = line.replace('event:', '').trim()
              } else if (line.startsWith('data:')) {
                eventData.data = line.replace('data:', '').trim()
              } else if (line.startsWith('id:')) {
                eventData.id = line.replace('id:', '').trim()
              }
            })
            console.log(eventData)
            // 回调处理解析后的数据
            let jsonData = {}
            if (eventData.event == 'answer') {
              jsonData = {
                data: JSON.parse(convertLineBreaksToEscaped(eventData.data))
              }
            } else if (eventData.event == 'full') {
              jsonData = {
                data: JSON.parse(convertLineBreaksToEscaped(eventData.data))
              }
            } else {
              jsonData = {
                data: JSON.parse(convertLineBreaksToNode(eventData.data))
              }
            }
            if (jsonData.data && Object.keys(jsonData.data).length) {
              // 尝试解析JSON数据 event(answer、issues、guess)
              let data = {
                code: 0,
                data: { event: eventData.event, id: eventData.id, ...jsonData.data },
                isError: true,
                isSuccess: true,
                msg: ''
              }
              if (callback) {
                callback(data)
              }
            }
          }
        })
      } catch (error) {
        console.error('SSE数据解析错误:', error)
      }
    })
  })
}


回答关注问题邀请回答
收藏

1 个回答

  • 智能回答 智能回答 本次回答由AI生成
    01-04
    有用
    回复 1
    • 军
      01-13
      1、看图
      2、这个请求包上次发过
      3、基础库最低可用版本3.6.5
      5.网络环境信息(WiFi/4G)全部出现过
      01-13
      回复
登录 后发表内容