fix: 修复流式聊天发生错误时继续处理后续事件的问题
- 增加 hasError 标记,错误发生后立即停止处理后续事件 - 在 done 事件处理前检查是否已有错误 - 在 finally 中确保 reader 被正确关闭 - 防止错误发生后,done 事件继续执行导致历史响应被错误回填main
parent
c30d301fbc
commit
92ef2c38c8
17
src/api.ts
17
src/api.ts
|
|
@ -757,15 +757,18 @@ async function consumeSSE(resp: Response, h: StreamEvents, signal?: AbortSignal)
|
|||
const reader = resp.body.getReader();
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
let buf = '';
|
||||
let hasError = false; // 标记是否已发生错误,避免后续事件继续处理
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
if (done || hasError) break;
|
||||
|
||||
buf += decoder.decode(value, { stream: true });
|
||||
buf = buf.replace(/\r\n/g, '\n');
|
||||
|
||||
let idx;
|
||||
while ((idx = buf.indexOf('\n\n')) !== -1) {
|
||||
while ((idx = buf.indexOf('\n\n')) !== -1 && !hasError) {
|
||||
const raw = buf.slice(0, idx);
|
||||
buf = buf.slice(idx + 2);
|
||||
if (!raw.trim() || raw.startsWith(':')) continue;
|
||||
|
|
@ -807,13 +810,18 @@ async function consumeSSE(resp: Response, h: StreamEvents, signal?: AbortSignal)
|
|||
h.onToolResult?.(data);
|
||||
break;
|
||||
case 'done':
|
||||
h.onDone?.(data);
|
||||
// 只有在没有错误的情况下才处理 done 事件
|
||||
if (!hasError) {
|
||||
h.onDone?.(data);
|
||||
}
|
||||
break;
|
||||
case 'aborted':
|
||||
h.onAborted?.(data);
|
||||
break;
|
||||
case 'error':
|
||||
hasError = true;
|
||||
h.onError?.(data.message || 'stream error');
|
||||
// 发生错误后立即停止读取
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -824,6 +832,9 @@ async function consumeSSE(resp: Response, h: StreamEvents, signal?: AbortSignal)
|
|||
return;
|
||||
}
|
||||
h.onError?.(e?.message ?? String(e));
|
||||
} finally {
|
||||
// 确保 reader 被释放
|
||||
reader.cancel().catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue