从卡顿到丝滑,AI 应用体验跃升的幕后推手是它!

作者:程序员成长指北

原文:mp.weixin.qq.com/s/qsbidng1b...

大家好,今天咱们聊点有意思的:为什么你用 AI 聊天,有时候秒回,有时候却像"掉线"了一样半天没反应?其实,这背后有不少门道,尤其是服务端推送这招,能让你的 Web 应用体验大大提升!

为什么响应慢?大模型的"慢动作"

先来点背景知识。

现在的 AI 大模型,像 ChatGPT、Deepseek 这些,都是现点现做---你问一句,它现场推理、现场生成答案,然后再把结果打包成 JSON,通过 HTTP 协议丢给前端。

问题来了:推理时间和你问的问题复杂度、生成的内容多少(token 数)直接挂钩。你要是问个你好,AI 一秒就能回你。但你要它写一篇小说大纲,或者来个千字作文,AI 得「冥想」好一会儿。这时候,用户就只能干等着,体验很一般。

但你有没有发现,很多大模型的 Web 端其实响应很快?秘诀就是:流式(streaming)传输!不用等答案全生成完,AI 生成一点就推一点,前端边收边展示,体验直接拉满!

什么是服务端推送?为啥它这么香?

服务端推送,顾名思义,就是服务器主动把消息"推"给你,而不是你一直去问有新消息吗。这就像外卖小哥主动敲门送餐,而不是你每隔五分钟打电话问饭做好了吗

服务端推送的好处:

  • 实时通知:新消息、活动提醒、外卖状态......都能第一时间送到你手上。
  • 省资源:不用客户端一直"轮询"服务器,省流量、省算力,服务器也轻松。
  • 体验好:还能给你推送个性化内容,比如专属优惠、直播提醒,用户粘性蹭蹭涨!

常见场景有:微信消息、新闻推送、外卖进度......你手机上各种推送,基本都靠这套

常见的实时通信方案大盘点

传统轮询 & 长轮询

  • 轮询 :客户端定时问有新消息吗?,服务器回有/没有。实现简单,但延迟高、资源消耗大。
  • 长轮询 :升级版。客户端问一次,服务器没新消息就憋着,有了再回。减少了请求次数,但还是有延迟。

HTML5 新玩法:WebSocket & SSE

  • WebSocket:双向实时通信,适合互动性强的场景,比如在线聊天、游戏。
  • SSE:服务端单向推送,适合消息通知、进度更新等场景,简单易用。
特性 SSE(Server-Sent Events) WebSocket
协议 HTTP TCP
通信方向 单向(服务端→客户端) 双向
实现复杂度 简单 稍复杂
自动重连 内置 需手动实现
数据格式 文本/二进制 类型广泛
事件支持 支持自定义事件 不支持
连接数限制 有(HTTP/1.1 6个) 基本无限制
浏览器支持 主流支持,IE不行 主流都支持

第三方推送服务

常见的有操作系统提供相应的推送服务,如苹果的APNs(Apple Push Notification service)、谷歌的FCM(Firebase Cloud Messaging)等。同时,也有一些跨平台的推送服务,如个推、极光推送、友盟推送等,帮助开发者在不同平台上实现统一的推送功能。

这种推送方式在生活中十分常见,一般你打开手机就能看到各种信息推送,基本就是利用第三方推送来实现。

SSE

SSE(Server-Sent Events)就是服务端推送的「轻骑兵」,基于 HTTP 协议,部署简单,特别适合服务器主动推消息,客户端只需接收的场景。

EventSource:用起来超简单

SSE 在前端的入口就是 EventSource

EventSource 接受两个参数:URL 和 options。

  • URL:就是服务器发流的地址,写上它,浏览器立刻自动给你搭通道,一有消息就往下传。
  • options(可选参数):里边有个 withCredentials,决定要不要带上 cookie、HTTP 认证啥的。默认是 false,就是不带,如果想带就设置成 true。

你只需要几行代码,就能和服务器建立实时通道

javascript 复制代码
const eventSource = new EventSource('http_api_url', { withCredentials: true });

// 监听连接开启
eventSource.addEventListener('open', event => {
console.log('连接已开启');
});

// 监听消息
eventSource.addEventListener('message', event => {
console.log('收到消息:', event.data);
});

// 监听自定义事件
eventSource.addEventListener('myEvent', event => {
console.log('收到自定义事件:', event.data);
});

// 监听错误
eventSource.addEventListener('error', event => {
console.log('出错啦:', event);
});

// 关闭连接
eventSource.close();

是不是很简单?而且还能自动重连,断了也不怕!

Stream API:数据流处理更灵活

Stream API 让你可以像流水线一样处理网络数据,把大文件、长内容分块处理,边下边用,效率高还不卡顿。

@microsoft/fetch-event-source

虽然浏览器自带的 EventSource 很好用,但有些场景它就有点「力不从心」了,比如:

  • 不能带请求体(body),只能 GET,不能自定义请求头
  • 断线重连策略不可控
  • 只能用浏览器原生实现

这时候,@microsoft/fetch-event-source 就派上用场了!它基于 Fetch API,支持各种请求方式、请求头、请求体,还能自定义重试策略,灵活到飞起!

用法示例:

javascript 复制代码
import { fetchEventSource } from"@microsoft/fetch-event-source";

const controller = new AbortController();

fetchEventSource("https://demo.com/chat", {
method: "POST",
body: JSON.stringify({ message: "你好,AI!" }),
headers: { "Content-Type": "application/json" },
signal: controller.signal,
  onopen(response) {
    // 连接已建立
  },
  onmessage(msg) {
    console.log("收到消息:", msg.data);
  },
  onclose() {
    console.log("连接关闭");
  },
  onerror(err) {
    controller.abort();
    console.error("出错啦:", err);
  }
})

AbortController:优雅地中断请求

有时候,用户点了取消或者页面跳转了,咱们就得把还在进行的网络请求停掉。这时候,AbortController 就是你的好帮手!

用法:

ini 复制代码
const controller = new AbortController();
const signal = controller.signal;

fetch(url, { signal })
  .then(response => { /* 处理响应 */ })
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('请求被取消');
    } else {
      // 其他错误
    }
  });

// 需要取消时
controller.abort();

现在你知道了吧?想让你的 Web 应用秒回,服务端推送(尤其是 SSE)绝对是个好选择!不管是消息通知、AI 聊天、进度更新,体验都能大大提升。赶紧试试吧,让你的产品人一步!

相关推荐
嘉小华2 分钟前
大白话讲解 Android屏幕适配相关概念(dp、px 和 dpi)
前端
姑苏洛言2 分钟前
在开发跑腿小程序集成地图时,遇到的坑,MapContext.includePoints(Object object)接口无效在组件中使用无效?
前端
七八书6 分钟前
Vue3 组件通信全解析:从基础到进阶的实用指南
vue.js
奇舞精选6 分钟前
Prompt 工程实用技巧:掌握高效 AI 交互核心
前端·openai
用户3802258598247 分钟前
vue3源码解析:模块总览
vue.js
Danny_FD19 分钟前
React中可有可无的优化-对象类型的使用
前端·javascript
用户7575823185521 分钟前
混合应用开发:企业降本增效之道——面向2025年移动应用开发趋势的实践路径
前端
P1erce31 分钟前
记一次微信小程序分包经历
前端
LeeAt32 分钟前
从Promise到async/await的逻辑演进
前端·javascript
等一个晴天丶33 分钟前
不一样的 TypeScript 入门手册
前端