🐛 fix(chat): improve error handling and UI feedback for SSE communication

- Add comprehensive error handling for SSE events
- Implement proper error state UI with Semi Typography
- Prevent white screen issues on non-200 responses
- Add error logging for better debugging
- Enhance message state management for error conditions
- Improve user feedback with i18n error messages
- Ensure UI stability during error states
- Add try-catch blocks for JSON parsing and stream initialization
- Handle connection termination gracefully
- Preserve error states in message stream updates
This commit is contained in:
Apple\Apple
2025-05-26 19:58:01 +08:00
parent 0298692852
commit d96eb6fb1c

View File

@@ -203,6 +203,7 @@ const Playground = () => {
method: 'POST',
payload: JSON.stringify(payload),
});
source.addEventListener('message', (e) => {
if (e.data === '[DONE]') {
source.close();
@@ -210,32 +211,51 @@ const Playground = () => {
return;
}
let payload = JSON.parse(e.data);
const delta = payload.choices?.[0]?.delta;
if (delta) {
if (delta.reasoning_content) {
streamMessageUpdate(delta.reasoning_content, 'reasoning');
}
if (delta.content) {
streamMessageUpdate(delta.content, 'content');
try {
let payload = JSON.parse(e.data);
const delta = payload.choices?.[0]?.delta;
if (delta) {
if (delta.reasoning_content) {
streamMessageUpdate(delta.reasoning_content, 'reasoning');
}
if (delta.content) {
streamMessageUpdate(delta.content, 'content');
}
}
} catch (error) {
console.error('Failed to parse SSE message:', error);
streamMessageUpdate(t('解析响应数据时发生错误'), 'content');
completeMessage('error');
}
});
source.addEventListener('error', (e) => {
streamMessageUpdate(e.data, 'content');
console.error('SSE Error:', e);
const errorMessage = e.data || t('请求发生错误');
streamMessageUpdate(errorMessage, 'content');
completeMessage('error');
source.close();
});
source.addEventListener('readystatechange', (e) => {
if (e.readyState >= 2) {
if (source.status === undefined) {
if (source.status === undefined || source.status !== 200) {
source.close();
completeMessage();
streamMessageUpdate(t('连接已断开'), 'content');
completeMessage('error');
} else if (source.status === 200) {
// 正常状态,不需要特殊处理
}
}
});
source.stream();
try {
source.stream();
} catch (error) {
console.error('Failed to start SSE stream:', error);
streamMessageUpdate(t('建立连接时发生错误'), 'content');
completeMessage('error');
}
};
const onMessageSend = useCallback(
@@ -303,10 +323,13 @@ const Playground = () => {
setMessage((prevMessage) => {
const lastMessage = prevMessage[prevMessage.length - 1];
let newMessage = { ...lastMessage };
if (
lastMessage.status === 'loading' ||
lastMessage.status === 'incomplete'
) {
// 如果消息已经是错误状态,保持错误状态
if (lastMessage.status === 'error') {
return prevMessage;
}
if (lastMessage.status === 'loading' || lastMessage.status === 'incomplete') {
if (type === 'reasoning') {
newMessage = {
...newMessage,
@@ -379,6 +402,19 @@ const Playground = () => {
const renderCustomChatContent = useCallback(
({ message, className }) => {
if (message.status === 'error') {
return (
<div className={className} style={{
display: 'flex',
alignItems: 'center',
padding: '12px',
color: 'var(--semi-color-danger)'
}}>
<Typography.Text type="danger">{message.content || t('请求发生错误')}</Typography.Text>
</div>
);
}
const toggleReasoningExpansion = (messageId) => {
setMessage(prevMessages =>
prevMessages.map(msg =>