diff --git a/app/(tabs)/ask.tsx b/app/(tabs)/ask.tsx index b9bb8f3..bf426e8 100644 --- a/app/(tabs)/ask.tsx +++ b/app/(tabs)/ask.tsx @@ -100,105 +100,141 @@ export default function AskScreen() { useFocusEffect( useCallback(() => { - webSocketManager.connect(); + // 添加一个标志来检查组件是否已卸载 + let isMounted = true; + + // 确保在组件挂载时才连接 + if (isMounted) { + webSocketManager.connect(); + } const handleChatStream = (message: WsMessage) => { + // 确保组件仍然挂载 + if (!isMounted) return; + if (message.type === 'ChatStream') { setUserMessages(prevMessages => { - const lastMessage = prevMessages[prevMessages.length - 1]; - - // 检查是否是有效的助手消息 - if (!lastMessage || lastMessage.role !== Assistant) { + // 使用 try-catch 包装以防止错误导致应用崩溃 + try { + const lastMessage = prevMessages[prevMessages.length - 1]; + + // 检查是否是有效的助手消息 + if (!lastMessage || lastMessage.role !== Assistant) { + return prevMessages; + } + + // 创建新的消息数组 + const newMessages = [...prevMessages]; + + if (typeof lastMessage.content === 'string') { + if (lastMessage.content === 'keepSearchIng') { + // 第一次收到流式消息,替换占位符 + newMessages[newMessages.length - 1] = { + ...lastMessage, + content: message.chunk + }; + } else { + // 持续追加流式消息 + newMessages[newMessages.length - 1] = { + ...lastMessage, + content: lastMessage.content + message.chunk + }; + } + } else if (Array.isArray(lastMessage.content)) { + // 如果 content 是数组,则更新第一个 text 部分 + const textPartIndex = lastMessage.content.findIndex(p => p.type === 'text'); + if (textPartIndex !== -1) { + const updatedContent = [...lastMessage.content]; + updatedContent[textPartIndex] = { + ...updatedContent[textPartIndex], + text: (updatedContent[textPartIndex].text || '') + message.chunk + }; + + newMessages[newMessages.length - 1] = { + ...lastMessage, + content: updatedContent + }; + } + } + + return newMessages; + } catch (error) { + console.error('处理 ChatStream 消息时出错:', error); + // 发生错误时返回原始消息数组 return prevMessages; } - - // 创建新的消息数组 - const newMessages = [...prevMessages]; - - if (typeof lastMessage.content === 'string') { - if (lastMessage.content === 'keepSearchIng') { - // 第一次收到流式消息,替换占位符 - newMessages[newMessages.length - 1] = { - ...lastMessage, - content: message.chunk - }; - } else { - // 持续追加流式消息 - newMessages[newMessages.length - 1] = { - ...lastMessage, - content: lastMessage.content + message.chunk - }; - } - } else { - // 如果 content 是数组,则更新第一个 text 部分 - const textPartIndex = lastMessage.content.findIndex(p => p.type === 'text'); - if (textPartIndex !== -1) { - const updatedContent = [...lastMessage.content]; - updatedContent[textPartIndex] = { - ...updatedContent[textPartIndex], - text: (updatedContent[textPartIndex].text || '') + message.chunk - }; - - newMessages[newMessages.length - 1] = { - ...lastMessage, - content: updatedContent - }; - } - } - - return newMessages; }); } }; const handleChatStreamEnd = (message: WsMessage) => { + // 确保组件仍然挂载 + if (!isMounted) return; + if (message.type === 'ChatStreamEnd') { setUserMessages(prevMessages => { - const lastMessage = prevMessages[prevMessages.length - 1]; - - // 检查是否是有效的助手消息 - if (!lastMessage || lastMessage.role !== Assistant) { - return prevMessages; - } + // 使用 try-catch 包装以防止错误导致应用崩溃 + try { + const lastMessage = prevMessages[prevMessages.length - 1]; - // 使用最终消息替换流式消息,确保 message.message 存在 - if (message.message) { - const newMessages = [...prevMessages]; - newMessages[newMessages.length - 1] = message.message as Message; - return newMessages; - } else { - // 如果最终消息为空,则移除 'keepSearchIng' 占位符 - return prevMessages.filter(m => - !(typeof m.content === 'string' && m.content === 'keepSearchIng') - ); + // 检查是否是有效的助手消息 + if (!lastMessage || lastMessage.role !== Assistant) { + return prevMessages; + } + + // 使用最终消息替换流式消息,确保 message.message 存在 + if (message.message) { + const newMessages = [...prevMessages]; + newMessages[newMessages.length - 1] = message.message as Message; + return newMessages; + } else { + // 如果最终消息为空,则移除 'keepSearchIng' 占位符 + return prevMessages.filter(m => + !(typeof m.content === 'string' && m.content === 'keepSearchIng') + ); + } + } catch (error) { + console.error('处理 ChatStreamEnd 消息时出错:', error); + // 发生错误时返回原始消息数组 + return prevMessages; } }); } }; const handleError = (message: WsMessage) => { + // 确保组件仍然挂载 + if (!isMounted) return; + if (message.type === 'Error') { console.log(`WebSocket Error: ${message.code} - ${message.message}`); - + setUserMessages(prevMessages => { - const lastMessage = prevMessages[prevMessages.length - 1]; - - // 检查是否是有效的助手消息且包含占位符 - if (!lastMessage || - lastMessage.role !== Assistant || - typeof lastMessage.content !== 'string' || - lastMessage.content !== 'keepSearchIng') { + // 使用 try-catch 包装以防止错误导致应用崩溃 + try { + const lastMessage = prevMessages[prevMessages.length - 1]; + + // 检查是否是有效的助手消息且包含占位符 + if (!lastMessage || + lastMessage.role !== Assistant || + typeof lastMessage.content !== 'string' || + lastMessage.content !== 'keepSearchIng') { + return prevMessages; + } + + // 替换占位符为错误消息 + const newMessages = [...prevMessages]; + newMessages[newMessages.length - 1] = { + ...lastMessage, + content: getWebSocketErrorMessage(message.code, t) + }; + + return newMessages; + } catch (error) { + console.error('处理 Error 消息时出错:', error); + // 发生错误时返回原始消息数组 return prevMessages; } - - // 替换占位符为错误消息 - const newMessages = [...prevMessages]; - newMessages[newMessages.length - 1] = { - ...lastMessage, - content: getWebSocketErrorMessage(message.code, t) - }; - - return newMessages; }); } }; @@ -208,11 +244,16 @@ export default function AskScreen() { webSocketManager.subscribe('Error', handleError); return () => { + // 设置组件卸载标志 + isMounted = false; + + // 清理订阅 webSocketManager.unsubscribe('ChatStream', handleChatStream); webSocketManager.unsubscribe('ChatStreamEnd', handleChatStreamEnd); webSocketManager.unsubscribe('Error', handleError); + // 可以在这里选择断开连接,或者保持连接以加快下次进入页面的速度 - // webSocketManager.disconnect(); + webSocketManager.disconnect(); }; }, [t]) );