Skip to content

Commit ddb8f7d

Browse files
committed
fix: Huge chunk write error
1 parent 09ef1a5 commit ddb8f7d

File tree

1 file changed

+54
-50
lines changed

1 file changed

+54
-50
lines changed

ui/src/components/ai-chat/index.vue

Lines changed: 54 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -423,73 +423,77 @@ function getChartOpenId(chat?: any, problem?: string, re_chat?: boolean, other_p
423423
*/
424424
const getWrite = (chat: any, reader: any, stream: boolean) => {
425425
let tempResult = ''
426-
/**
427-
*
428-
* @param done 是否结束
429-
* @param value
430-
*/
431-
const write_stream = ({ done, value }: { done: boolean; value: any }) => {
426+
427+
const write_stream = async () => {
432428
try {
433-
if (done) {
434-
ChatManagement.close(chat.id)
435-
return
436-
}
437-
const decoder = new TextDecoder('utf-8')
438-
let str = decoder.decode(value, { stream: true })
439-
// 这里解释一下 start 因为数据流返回流并不是按照后端chunk返回 我们希望得到的chunk是data:{xxx}\n\n 但是它获取到的可能是 data:{ -> xxx}\n\n 总而言之就是 fetch不能保证每个chunk都说以data:开始 \n\n结束
440-
tempResult += str
441-
const split = tempResult.match(/data:.*}\n\n/g)
442-
if (split) {
443-
str = split.join('')
444-
tempResult = tempResult.replace(str, '')
445-
} else {
446-
return reader.read().then(write_stream)
447-
}
448-
// 这里解释一下 end
449-
if (str && str.startsWith('data:')) {
429+
while (true) {
430+
const { done, value } = await reader.read()
431+
432+
if (done) {
433+
ChatManagement.close(chat.id)
434+
return
435+
}
436+
437+
const decoder = new TextDecoder('utf-8')
438+
let str = decoder.decode(value, { stream: true })
439+
440+
tempResult += str
441+
const split = tempResult.match(/data:.*?}\n\n/g)
442+
450443
if (split) {
451-
for (const index in split) {
452-
const chunk = JSON?.parse(split[index].replace('data:', ''))
444+
str = split.join('')
445+
tempResult = tempResult.replace(str, '')
446+
447+
// 批量处理所有 chunk
448+
for (const item of split) {
449+
const chunk = JSON.parse(item.replace('data:', ''))
453450
chat.chat_id = chunk.chat_id
454451
chat.record_id = chunk.chat_record_id
452+
455453
if (!chunk.is_end) {
456454
ChatManagement.appendChunk(chat.id, chunk)
457455
}
456+
458457
if (chunk.is_end) {
459-
// 流处理成功 返回成功回调
460458
return Promise.resolve()
461459
}
462460
}
463461
}
462+
// 如果没有匹配到完整chunk,继续读取下一块
464463
}
465464
} catch (e) {
466465
return Promise.reject(e)
467466
}
468-
return reader.read().then(write_stream)
469467
}
470-
/**
471-
* 处理 json 响应
472-
* @param param0
473-
*/
474-
const write_json = ({ done, value }: { done: boolean; value: any }) => {
475-
if (done) {
476-
const result_block = JSON.parse(tempResult)
477-
if (result_block.code === 500) {
478-
return Promise.reject(result_block.message)
479-
} else {
480-
if (result_block.content) {
481-
ChatManagement.append(chat.id, result_block.content)
468+
469+
const write_json = async () => {
470+
try {
471+
while (true) {
472+
const { done, value } = await reader.read()
473+
474+
if (done) {
475+
const result_block = JSON.parse(tempResult)
476+
if (result_block.code === 500) {
477+
return Promise.reject(result_block.message)
478+
} else {
479+
if (result_block.content) {
480+
ChatManagement.append(chat.id, result_block.content)
481+
}
482+
}
483+
ChatManagement.close(chat.id)
484+
return
485+
}
486+
487+
if (value) {
488+
const decoder = new TextDecoder('utf-8')
489+
tempResult += decoder.decode(value)
482490
}
483491
}
484-
ChatManagement.close(chat.id)
485-
return
486-
}
487-
if (value) {
488-
const decoder = new TextDecoder('utf-8')
489-
tempResult += decoder.decode(value)
492+
} catch (e) {
493+
return Promise.reject(e)
490494
}
491-
return reader.read().then(write_json)
492495
}
496+
493497
return stream ? write_stream : write_json
494498
}
495499
const errorWrite = (chat: any, message?: string) => {
@@ -646,7 +650,7 @@ const handleScroll = () => {
646650
// 内部高度小于外部高度 就需要出滚动条
647651
if (scrollDiv.value.wrapRef.offsetHeight < dialogScrollbar.value.scrollHeight) {
648652
// 滚动到底部
649-
scrollDiv.value.setScrollTop(dialogScrollbar.value.scrollHeight);
653+
scrollDiv.value.setScrollTop(dialogScrollbar.value.scrollHeight)
650654
}
651655
}
652656
}
@@ -758,10 +762,10 @@ watch(
758762
chatList,
759763
() => {
760764
nextTick(() => {
761-
handleScroll(); // 确保 DOM 更新后再滚动
762-
});
765+
handleScroll() // 确保 DOM 更新后再滚动
766+
})
763767
},
764-
{deep: true, immediate: true},
768+
{ deep: true, immediate: true },
765769
)
766770
767771
defineExpose({

0 commit comments

Comments
 (0)