fix(ai): 修复WebSocket重复回调及意外关闭问题

This commit is contained in:
2026-05-11 17:14:26 +08:00
parent dee2887026
commit e16402c9c1
2 changed files with 55 additions and 13 deletions

View File

@@ -88,6 +88,16 @@ export default {
return new Promise((resolve, reject) => {
const match = Config.baseUrl.match(/^(?:https?:\/\/|wss?:\/\/)([^\/\s:]+)/);
const domain = match ? match[1] : '';
// 修复 5:Domain 提取失败时提前拒绝
if (!domain) {
const errorMsg = 'WebSocket 域名配置无效';
console.error(errorMsg);
reject(new Error(errorMsg));
if (onComplete) onComplete({ error: errorMsg });
return;
}
const wssUrl = `wss://${domain}/ws/aikefu`;
const socketTask = wx.connectSocket({
url: wssUrl,
@@ -97,6 +107,29 @@ export default {
let content = '';
let conversationId = '';
let isAuthenticated = false;
let closedNormally = false;
let settled = false;
// 安全地拒绝(防止重复调用)
function safeReject(error) {
if (settled) return;
settled = true;
clearTimeout(timeout);
reject(error);
}
// 安全地完成
function safeResolve(result) {
if (settled) return;
settled = true;
clearTimeout(timeout);
resolve(result);
}
// 安全地触发 onComplete
function safeComplete(result) {
if (onComplete) onComplete(result);
}
socketTask.onOpen(() => {
socketTask.send({
@@ -128,8 +161,8 @@ export default {
} else if (data.type === 'auth_failed') {
const errorMsg = '认证失败,请重新登录';
console.error(errorMsg, data);
reject(new Error(errorMsg));
if (onComplete) onComplete({ error: errorMsg });
safeComplete({ error: errorMsg });
safeReject(new Error(errorMsg));
socketTask.close();
}
@@ -146,10 +179,9 @@ export default {
if (conversationId) {
this.setConversationId(conversationId);
}
if (onComplete) {
onComplete({ content, conversation_id: conversationId });
}
resolve({ content, conversation_id: conversationId });
closedNormally = true;
safeComplete({ content, conversation_id: conversationId });
safeResolve({ content, conversation_id: conversationId });
socketTask.close();
}
@@ -165,21 +197,27 @@ export default {
socketTask.onError((err) => {
const errorMsg = 'WebSocket 连接失败';
console.error(errorMsg, err);
reject(new Error(errorMsg));
if (onComplete) onComplete({ error: errorMsg });
safeComplete({ error: errorMsg });
safeReject(new Error(errorMsg));
});
socketTask.onClose(() => {
if (!closedNormally && !settled) {
const errorMsg = 'WebSocket 连接意外关闭';
console.error(errorMsg);
safeComplete({ error: errorMsg });
safeReject(new Error(errorMsg));
}
});
const timeout = setTimeout(() => {
if (!isAuthenticated || content === '') {
console.warn('WebSocket 超时,强制关闭');
socketTask.close();
reject(new Error('AI服务响应超时'));
if (onComplete) onComplete({ error: 'AI服务响应超时' });
safeComplete({ error: 'AI服务响应超时' });
safeReject(new Error('AI服务响应超时'));
}
}, 10000);
}, 20000);
});
// #endif
},

View File

@@ -1010,8 +1010,10 @@ async loadChatHistoryIfExist() {
await aiService.sendHttpStream(
userMessage,
(chunk) => {
// 实时更新内容(不频繁滚动)
// 实时更新内容
streamMessage.content += chunk;
// 流式更新时滚动到底部显示最新内容(防抖)
this.scrollToBottom();
},
(completeResult) => {
// 流结束回调
@@ -1054,8 +1056,10 @@ async loadChatHistoryIfExist() {
await aiService.sendStreamMessage(
userMessage,
(chunk) => {
// 实时更新内容(不频繁滚动)
// 实时更新内容
streamMessage.content += chunk;
// 流式更新时滚动到底部显示最新内容(防抖)
this.scrollToBottom();
},
(completeResult) => {
// 流结束回调