96SEO 2026-07-23 22:00 2
怎么说呢,
项目技术栈Node.js + Express + 阿里云百炼 + SSE + Zustand 主要目标实现文档自动切片、向量索引建立和智能问答功能。
适用场景React 前端状态管理、SSE 长连接处理 大神提示本篇主要记录前端如何优雅地处理异步任务轮询。避免重复请求,大神可略过求轻喷 🙏

本篇是 RAG 程序的前端收尾环节。虽接下来端已经实现了状态流转,但如果前端做得不好。很容易出现“重复建立连接”或“内存泄漏”的问题。
主要原因是:Zustand 全局状态去重 + 单例连接控制。
在 SPA中,使用者可能会频繁切换页面或组件重渲染。老实说,如果没有状态管理:
方法:
Set 存储所有“正在进行的任务 ID”。本篇分为两部分:状态定义和连接逻辑。
使用 Set 而不是 Array因为 Set 天然保证唯一性。且 .has 查找速度是 O,比数组的 .includes) 更快。
import { create } from 'zustand';// 类型定义
interface TaskState {
activeTaskIds: Set;actions: {
addTask: => void;removeTask: => void;},}
const useTaskStore = create => ({
activeTaskIds: new Set,actions: {
addTask: =>
set => {
const newSet = new Set;newSet.add,// 如果已存在Set 会自动忽略
return { activeTaskIds: newSet };}),removeTask: =>
set => {
const newSet = new Set;newSet.delete;return { activeTaskIds: newSet };}),},})),// 导出 Hook
export { useTaskStore };export const useTaskActions = => useTaskStore => state.actions);export const useActiveTaskIds = => useTaskStore => state.activeTaskIds);
listeningTasks 是关键调整点。怎么说呢,Zustand 中的 activeTaskIds 用于 UI 驱动视图更新。而 listeningTasks 用于逻辑层防止重复执行,两者结合才能保证万无一失。
import { message } from "antd";import { useTaskStore } from "@/store";
import { getTaskListAction } from "@/api/rag";话说回来,// 🔑 关键:逻辑层的去重 Set
// Zustand 是为了驱动 UI 更新。这个 Set 是为了防止代码逻辑重复执行
const listeningTasks = new Set;/**
* 启动单个任务的监听器
* @param taskId 任务 ID
*/
export const startTaskListener = async => {
// ✅ 第一层防御:逻辑层去重
// 即使组件多次调用,这里也能拦截住
if ) {
console.log;return,}
listeningTasks.add;console.log,try {
const response = await fetch(`/proxy/api/ragEngine/getFileStatus/${taskId}`,{
说到method,'GET'。headers: {
'Content-Type': 'application/json','Authorization': `Bearer ${localStorage.getItem}`,},});if {
throw new Error;}
const reader = response.body?话说回来,.getReader;按理说,const decoder = new TextDecoder;// ✅ 第二层防御:无限循环读取流
// done 为 true 时才会退出
while {
const { done,value } = await reader.read;if break,const chunk = decoder.decode;其实,const lines = chunk.split;for {
if ) {
const dataStr = line.slice.trim;try {
const parsed = JSON.parse;说起来,console.log;// ✅ 第三层防御:状态判断与清理
// 只有成功或失败才清理,否则一直挂着
if {
message.success;// . 通知 Store 移除任务
useTaskStore.getState.actions.removeTask;// . 退出循环,断开连接
return;}
} catch {
console.warn;}
}
}
}
} catch {
if {
console.log;老实说,} else {
console.error;message.error;}
} finally {
// ✅ 第四层防御:确保清理逻辑层状态
listeningTasks.delete;}
},/**
* 初始化全局监听器
* 应用启动时调用,恢复上次未完成的任务
*/
export const initGlobalTaskListener = => {
getTaskListAction.n => {
if return;话说回来,// 筛选出还在进行中的任务
const tasks = res.data.filter=>!.includes),tasks.forEach=>{
// . 先加入 Store,防止页面上的按钮重复点击
useTaskStore.getState.actions.addTask;// . 开启监听
startTaskListener;}),});},
Set 而不是 /Array?| 数据结构 | 适用场景 | 本项目场景分析 |
|---|---|---|
| Aarray | - 有序列表 - 常需遍历或下标访问 | - 每次检查 ID 是否存在需要遍历 ) - 效率低且代码冗余。不合适 |
| MMap | - 键值对存储 - 当需要关联额外信息时使用 | - 项目只关心 “ID 是否存在”,不需要额外值 - 使用 Map 属于过度设计 |
| SSet | - 存储唯一值 - 快速判定是否存在 | - 完全匹配需求:“这个任务 ID 正在运行吗?” - 自动去重、查找 O,最合适 |
💡 : 至此。我们的 RAG 程序前端状态管理闭环了。从使用者上传文件开始,到后端处理,再到前端实时感知,整个流程已经跑通。
Main.tsx / App.tsx 或路由守卫中调用 {`initGlobalTaskListener`}.{`useTaskActions.addTask`} 和 {`startTaskListener`}.`
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback