当前位置: 首页 > news >正文

useState为异步,测试一下编码时候是否考虑?

private markBotMessageAsFinished(success: boolean, status: ChatMessage['status'], finalContent?: string) {if (this.botMessageId) {this.handler.setHistoryContent(prev =>{console.log(prev);const updated=prev.map(msg =>{/*  console.log(msg.id);console.log( this.botMessageId) */return msg.id === this.botMessageId? {...msg,isStreaming: false,status,content: finalContent ?? msg.content}: msg})console.log(updated);return updated;});this.botMessageId = null;}}

为什么执行:msg.id === this.botMessageId,始终为false,打印发现 this.botMessageId为null了,出现这种该情况只有setHistoryContent为异步(useStae)!!!,果然AI没识别出来,一个点卡死整个功能异常

 const [aiMessages, setAiMessages] = useState<ChatMessage[]>([]);// Memoize the MessageService instance using useRefconst messageService = useRef(new MessageService({setHistoryContent: (updater) => {setAiMessages(updater); // updater is a function that takes prev state and returns new state},onMessage: (type, content) => {if (type === 'success') message.success(content);if (type === 'error') message.error(content);},onStreamStart: () => { // Add new callback for stream startconsole.log("AIDialogContent: onStreamStart called. Setting isStreamingMessage to true.");setIsStreamingMessage(true);setLoading(true); // Ensure overall loading is true},onStreamCompleteOrError: () => {console.log("AIDialogContent: onStreamCompleteOrError called. Setting isStreamingMessage to false.");setIsStreamingMessage(false);setLoading(false); // Set overall loading to false when SSE connection closes (naturally, error, or manual stop)},setLastSuccessfulUserQuery: (query) => {setLastRequestContent(query);},esInstance: esWrapperInstance, // Pass the singleton EventSourceWrapper instance})).current; // Access .current immediately to get the instance

很好,你已经非常接近问题本质!让我们仔细理一理这个代码片段:

private markBotMessageAsFinished(success: boolean, status: ChatMessage['status'], finalContent?: string) {if (this.botMessageId) {// ⚡️ 在进入时 botMessageId 还有值const id = this.botMessageId;// ✅ 将 id 保存到局部变量this.handler.setHistoryContent(prev => {const updated = prev.map(msg => {return msg.id === id? {...msg,isStreaming: false,status,content: finalContent ?? msg.content}: msg;});return updated;});}this.botMessageId = null;
}

🔍 对这个异步性的疑问

  • setHistoryContent() 在多数情况下是同步调用同步更新状态,而非异步

    • 在 React 中,setState() 是异步批处理。

    • 在其他框架中,它也可能是同步或者异步。

    • 如果是 React,这里是同步调用更新器函数,只是最终 state 更新是异步批处理。所以:

      • 更新器中的代码是同步构建新值。
      • 更新器里面的 id 在进入 setHistoryContent() 时已经确定好了。
    • 即使后面因为某些原因 this.botMessageId 修改为 null也不影响已经捕获在局部变量中的 id


✅ 简而言之

  • 进入 markBotMessageAsFinished() 时,this.botMessageId 是有值的。
  • 在进入 setHistoryContent() 前,你已经用 const id = this.botMessageId 将值保存。
  • 即使后面 this.botMessageId = null 执行了,也不会改变已保存到局部变量 id 中的值。
  • setHistoryContent() 执行映射时,msg.id === id 始终成立,不会因为后续 this.botMessageId = null 改变行为

⚡️ 结论

❌ 这种情况下,不是因为异步导致检查失败。
✅ 原因通常是因为:

  • markBotMessageAsFinished() 被调用了 两次
  • 第一次调用修改好了状态。
  • 第二次调用进入时,this.botMessageId 已经是 null,导致后续没有修改。

即使是同步调用,后续调用也是受第一次调用修改状态影响。


⚡️ 最佳实践建议

  • 完全没必要因为异步而额外保存 id,但现在保存也是安全和标准做法。

  • 检查是否因为调用链 (handleEnd()onStreamCompleteOrError()) 重复调用。

  • 增加保护标记,例如:

    private finished = false;private markBotMessageAsFinished(success: boolean, status: ChatMessage['status'], finalContent?: string) {if (this.finished) {console.warn("markBotMessageAsFinished called multiple times");return;}this.finished = true;if (this.botMessageId) {const id = this.botMessageId;this.handler.setHistoryContent(prev =>prev.map(msg =>msg.id === id? {...msg,isStreaming: false,status,content: finalContent ?? msg.content,}: msg));}this.botMessageId = null;
    }
    

🎯 简单总结

✅ 你说对了一部分:「进入时没有 null」。
❌ 并非因为异步导致检测失败。
✔️ 原因是调用链里调用过两次,第一次修改后,第二次进入时 this.botMessageId 已为 null

http://www.lryc.cn/news/574784.html

相关文章:

  • Unity反射机制
  • mongoose解析http字段值
  • Spring Boot 的Banner的介绍和设置
  • 中科米堆3D扫描逆向建模方案:汽车轮毂三维扫描抄数建模
  • elk+filebeat收集springboot项目日志
  • iwebsec靶场-文件上传漏洞
  • 串口助手实例
  • lib61850 代码结构与系统架构深度分析
  • 鸿蒙OH南向开发 轻量系统内核(LiteOS-M)【异常调测】
  • 针对基于深度学习的侧信道分析(DLSCA)进行超参数的贝叶斯优化
  • vue 3 计算器
  • Nginx性能优化配置指南
  • 6.24_JAVA_微服务_Elasticsearch搜索
  • vscode + Jlink 一键调试stm32 单片机程序(windows系统版)
  • Git简介和常用命令
  • Windows安装Emscripten‌/emsdk(成功)
  • Python 数据分析与可视化 Day 6 - 可视化整合报告实战
  • Javaweb - 5 事件的绑定
  • 技术伦理之争:OpenAI陷抄袭风波,法院强制下架宣传视频
  • 自然语言处理入门
  • day041-web集群架构搭建
  • 软件设计模式选择、判断解析-1
  • 快速sincos算法,stm32测试
  • 用Rust写平衡三进制加法器
  • 【unitrix】 4.3 左移运算(<<)的实现(shl.rs)
  • 【WCF】单例模式的线程安全缓存管理器实现,给你的WebApi加入缓存吧
  • MyBatis Plus与P6Spy日志配置
  • leetcode230-二叉搜索树中第K小的元素
  • 【计算机网络】期末复习
  • 【教学类-89-08】20250624新年篇05——元宵节灯笼2CM黏贴边(倒置和正立数字 )