更新记录

1.0.0(2026-02-10) 下载此版本

支持Android sse


平台兼容性

uni-app(4.25)

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

uni-app x(4.25)

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

wxz-sse

支持 SSE(Server-Sent Events)的 UTS 插件,用法类似浏览器 EventSource API

功能特性

  • ✅ 支持 SSE 长连接,用于服务端向客户端推送实时数据
  • ✅ 支持 POST 请求携带 body 参数(需传字符串)
  • ✅ 支持自定义请求头 headers
  • ✅ 支持连接状态回调 onopenonmessageonerror
  • ✅ 基于系统 HttpURLConnection 实现,无第三方依赖
  • ✅ 支持 Android 平台(iOS、HarmonyOS 待实现)

使用方法

引入插件

import { createEventSource } from '@/uni_modules/wxz-sse'

创建 SSE 连接

const eventSource = createEventSource({
  url: 'https://your-server.com/sse',
  body: '{"key": "value"}',  // 可选,POST 请求体,必须为字符串
  headers: new Map([         // 可选,自定义请求头
    ['Authorization', 'Bearer xxx'],
    ['Content-Type', 'application/json']
  ]),
  onopen: (event) => {
    console.log('连接已打开', event);
  },
  onmessage: (event) => {
    console.log('收到消息:', event.data);
    // event 包含: data, type?, id?, origin?
  },
  onerror: (event) => {
    console.error('连接错误', event);
  }
});

断开连接

eventSource.close();

配置说明

EventSourceOptions 参数

参数 类型 必填 说明
url string SSE 服务器地址
body string POST 请求体,必须传字符串(如 JSON 需先 JSON.stringify),避免传对象导致序列化异常
headers Map<string, string> 自定义请求头
onopen (event: any) => void 连接成功回调
onmessage (event: EventSourceEvent) => void 收到消息回调,event 包含 data、type、id 等
onerror (event: any) => void 错误回调

EventSource 实例属性与方法

属性/方法 类型 说明
url string 连接地址
readyState number 连接状态:0=CONNECTING(连接中),1=OPEN(已连接),2=CLOSED(已关闭)
withCredentials boolean 是否携带凭证(当前固定为 false)
close() void 关闭连接

错误码

错误码 说明
9010001 连接失败
9010002 网络错误
9010003 连接已关闭

注意事项

  1. body 必须为字符串:若需传 JSON,请先 JSON.stringify(obj) 再传入,避免 proxy 序列化对象时产生异常。
  2. 自定义基座调试:UTS 插件需在「自定义基座」中运行,标准基座无法加载。操作步骤:运行 → 制作自定义调试基座 → 运行到真机。
  3. 生命周期:页面卸载时请调用 eventSource.close() 主动断开连接,避免资源泄漏。
  4. 网络权限:Android 需在 manifest 中配置网络权限(通常 uni-app 已默认配置)。

完整示例

以下是一个完整的 SSE 测试示例,支持连接、断开、接收消息展示:

<template>
  <view class="container">
    <view class="input-group">
      <text class="label">服务器地址:</text>
      <input class="input" v-model="serverUrl" placeholder="请输入 SSE 服务器地址" :disabled="isConnected" />
    </view>

    <view class="input-group">
      <text class="label">请求参数 (JSON):</text>
      <textarea class="textarea" v-model="requestBody" placeholder='{"key": "value"}' :disabled="isConnected" />
    </view>

    <view class="button-group">
      <button type="primary" @tap="connectSSE" :disabled="isConnected || !serverUrl">连接 SSE</button>
      <button type="warn" @tap="disconnectSSE" :disabled="!isConnected">断开连接</button>
    </view>

    <view class="status-section">
      <text>连接状态: {{ connectionStatus }}</text>
      <text>消息数量: {{ messages.length }}</text>
    </view>

    <view class="messages-section">
      <text class="section-title">接收到的消息:</text>
      <view v-for="(msg, index) in messages" :key="index" class="message-item">
        <text class="message-time">{{ msg.time }}</text>
        <text v-if="msg.type" class="message-type">{{ msg.type }}</text>
        <text class="message-data">{{ msg.data }}</text>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, computed, onUnmounted } from 'vue'
import { createEventSource } from '@/uni_modules/wxz-sse'

const READY_STATE = { CONNECTING: 0, OPEN: 1, CLOSED: 2 }

const serverUrl = ref('http://192.168.1.223:9901/sse')
const requestBody = ref('')
const isConnected = ref(false)
const messages = ref([])
let eventSource = null

const connectionStatus = computed(() => {
  if (!eventSource) return '未连接'
  switch (eventSource.readyState) {
    case READY_STATE.CONNECTING: return '连接中...'
    case READY_STATE.OPEN: return '已连接'
    case READY_STATE.CLOSED: return '已关闭'
    default: return '未知状态'
  }
})

const formatTime = () => {
  const now = new Date()
  return `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`
}

const addMessage = (event, type = 'message') => {
  messages.value.push({
    time: formatTime(),
    type: event.type || type,
    data: event.data || '',
    id: event.id || null
  })
}

const connectSSE = () => {
  if (!serverUrl.value.trim()) return
  try {
    const options = {
      url: serverUrl.value.trim(),
      onopen: (event) => {
        isConnected.value = true
        addMessage({ type: 'open', data: '连接已打开' }, 'open')
      },
      onmessage: (event) => {
        addMessage(event, 'message')
      },
      onerror: (event) => {
        addMessage({ type: 'error', data: event.data || '连接错误' }, 'error')
        if (eventSource?.readyState === READY_STATE.CLOSED) {
          isConnected.value = false
        }
      }
    }
    if (requestBody.value.trim()) {
      options.body = requestBody.value.trim()
    }
    eventSource = createEventSource(options)
    isConnected.value = true
  } catch (error) {
    let msg = error.message || String(error)
    if (msg.includes('not found') || msg.includes('wxz-sse')) {
      msg = '请使用「自定义基座」运行:运行 → 制作自定义调试基座 → 运行到真机'
    }
    uni.showToast({ title: msg, icon: 'none', duration: 4000 })
  }
}

const disconnectSSE = () => {
  if (eventSource) {
    eventSource.close()
    eventSource = null
    isConnected.value = false
  }
}

onUnmounted(() => {
  if (eventSource) {
    eventSource.close()
    eventSource = null
  }
})
</script>

开发文档

UTS 语法
UTS API插件
UTS uni-app兼容模式组件
UTS 标准模式组件
Hello UTS

隐私、权限声明

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

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

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

许可协议

MIT协议

暂无用户评论。