🐛 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:
@@ -203,6 +203,7 @@ const Playground = () => {
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
payload: JSON.stringify(payload),
|
payload: JSON.stringify(payload),
|
||||||
});
|
});
|
||||||
|
|
||||||
source.addEventListener('message', (e) => {
|
source.addEventListener('message', (e) => {
|
||||||
if (e.data === '[DONE]') {
|
if (e.data === '[DONE]') {
|
||||||
source.close();
|
source.close();
|
||||||
@@ -210,32 +211,51 @@ const Playground = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = JSON.parse(e.data);
|
try {
|
||||||
const delta = payload.choices?.[0]?.delta;
|
let payload = JSON.parse(e.data);
|
||||||
if (delta) {
|
const delta = payload.choices?.[0]?.delta;
|
||||||
if (delta.reasoning_content) {
|
if (delta) {
|
||||||
streamMessageUpdate(delta.reasoning_content, 'reasoning');
|
if (delta.reasoning_content) {
|
||||||
}
|
streamMessageUpdate(delta.reasoning_content, 'reasoning');
|
||||||
if (delta.content) {
|
}
|
||||||
streamMessageUpdate(delta.content, 'content');
|
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) => {
|
source.addEventListener('error', (e) => {
|
||||||
streamMessageUpdate(e.data, 'content');
|
console.error('SSE Error:', e);
|
||||||
|
const errorMessage = e.data || t('请求发生错误');
|
||||||
|
streamMessageUpdate(errorMessage, 'content');
|
||||||
completeMessage('error');
|
completeMessage('error');
|
||||||
|
source.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
source.addEventListener('readystatechange', (e) => {
|
source.addEventListener('readystatechange', (e) => {
|
||||||
if (e.readyState >= 2) {
|
if (e.readyState >= 2) {
|
||||||
if (source.status === undefined) {
|
if (source.status === undefined || source.status !== 200) {
|
||||||
source.close();
|
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(
|
const onMessageSend = useCallback(
|
||||||
@@ -303,10 +323,13 @@ const Playground = () => {
|
|||||||
setMessage((prevMessage) => {
|
setMessage((prevMessage) => {
|
||||||
const lastMessage = prevMessage[prevMessage.length - 1];
|
const lastMessage = prevMessage[prevMessage.length - 1];
|
||||||
let newMessage = { ...lastMessage };
|
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') {
|
if (type === 'reasoning') {
|
||||||
newMessage = {
|
newMessage = {
|
||||||
...newMessage,
|
...newMessage,
|
||||||
@@ -379,6 +402,19 @@ const Playground = () => {
|
|||||||
|
|
||||||
const renderCustomChatContent = useCallback(
|
const renderCustomChatContent = useCallback(
|
||||||
({ message, className }) => {
|
({ 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) => {
|
const toggleReasoningExpansion = (messageId) => {
|
||||||
setMessage(prevMessages =>
|
setMessage(prevMessages =>
|
||||||
prevMessages.map(msg =>
|
prevMessages.map(msg =>
|
||||||
|
|||||||
Reference in New Issue
Block a user