processChunk
函数中更新 questionList.value
后再更新 questionid.value
和 firstsendId.value
通过调整 questionid.value
和 firstsendId.value
更新的位置,我们可以确保它们的值在更新 questionList.value
之前就已经准备好:
const processChunk = (chunk: any) => {
if (paused.value === true) {
return;
}
const lines = chunk.split("\n").filter((line: any) => line.trim() !== "");
const newContent = lines.join("").replace(/\r/g, "");
const regex = /"data":"(.*?)"/g;
let match;
const results = [];
while ((match = regex.exec(newContent)) !== null) {
const cleanedData = match[1]
.replace(/^\n{2}/, "")
.replace(/\r/g, "")
.replace(/\n/g, "");
const parsedData = JSON.parse(`"${cleanedData}"`);
results.push(parsedData);
}
const answerSessionList = [];
const answerSessionRegex = /AnswerSessionRes\(id=(\d+), messageId=(\d+)\)/;
const answerSessions = results.filter((data) => answerSessionRegex.test(data));
console.log(results, "Results");
console.log(answerSessions, "answerSessions");
if (answerSessions.length > 0) {
answerSessions.forEach((session) => {
const matches = session.match(answerSessionRegex);
console.log(matches);
if (matches) {
const sessionObject = {
id: parseInt(matches[1], 10),
messageId: BigInt(matches[2])
};
console.log(sessionObject);
const serializedObj = JSON.stringify({
...sessionObject,
messageId: sessionObject.messageId.toString() // Convert BigInt to string
});
answerSessionList.push(serializedObj);
}
});
const jsonObject = JSON.parse(answerSessionList[0]);
// 先更新 questionid 和 messageIds
questionid.value = jsonObject.id;
messageIds.value = jsonObject.messageId;
firstsendId.value = jsonObject.messageId;
}
const filteredResults = results.filter((data) => !answerSessionRegex.test(data));
const sentence = filteredResults.join("");
// 然后再更新 questionList.value
questionList.value = sentence;
};
nextTick
使用 Vue.nextTick
确保在更新了 questionid.value
和 firstsendId.value
后,watch
函数可以在 DOM 更新后被调用。
在 processChunk
函数的最后,更新 questionList.value
时使用 nextTick
:
import { nextTick } from 'vue';
const processChunk = (chunk: any) => {
if (paused.value === true) {
return;
}
// 处理数据的逻辑...
if (answerSessions.length > 0) {
// 更新 questionid 和 firstsendId
questionid.value = jsonObject.id;
messageIds.value = jsonObject.messageId;
firstsendId.value = jsonObject.messageId;
}
const filteredResults = results.filter((data) => !answerSessionRegex.test(data));
const sentence = filteredResults.join("");
// 使用 nextTick 确保在 DOM 更新后才更新 questionList.value
nextTick(() => {
questionList.value = sentence;
});
};
await
确保顺序执行确保所有的异步操作都已完成,可以在更新 questionList.value
之前使用 await
确保顺序执行。
例如:
const processChunk = async (chunk: any) => {
if (paused.value === true) {
return;
}
// 处理数据的逻辑...
if (answerSessions.length > 0) {
// 更新 questionid 和 firstsendId
questionid.value = jsonObject.id;
messageIds.value = jsonObject.messageId;
firstsendId.value = jsonObject.messageId;
}
const filteredResults = results.filter((data) => !answerSessionRegex.test(data));
const sentence = filteredResults.join("");
// 更新 questionList.value
await new Promise((resolve) => setTimeout(resolve, 0)); // 强制下一次事件循环
questionList.value = sentence;
};
通过确保在更新 questionList.value
之前 questionid.value
和 firstsendId.value
已经更新,以上几种方法都可以解决你遇到的问题。选择适合你的代码逻辑的解决方案进行优化。
如果还不行的话......
watchEffect
代替 watch
watchEffect
会在依赖的响应式数据发生变化时立即执行,这样我们可以确保获取到最新的值。
import { watchEffect } from 'vue';
watchEffect(() => {
if (questionList.value) {
content.value[content.value.length - 1] = {
loading: false,
content: questionList.value,
role: AI_ROLE,
id: questionid.value,
messageId: firstsendId.value,
};
}
});
在 ass
函数内等待 getSessionJHistorys
异步函数完成并明确设置 id
和 messageId
。确保这些状态更新在下一个问题处理之前完成。
const ass = async (item: any) => {
if (canSend.value) {
canSend.value = false;
if (item.clearFlag) {
setTimeout(() => {
question.value = "";
}, 0);
}
} else {
message.warn("请等待上一个问题回答完再提问");
return;
}
ifhiddenText.value = false;
paused.value = false;
displayData.value = [];
content.value.push({
content: item.text || fileList.value[1].name,
role: USER_ROLE,
});
setTimeout(async () => {
content.value.push({
loading: true,
content: "内容生成中...",
role: AI_ROLE,
});
document.getElementById("bottom")?.scrollIntoView?.();
const formData = new FormData();
const jsonObject = {
rootTenantId: "151515",
tenantId: "222",
prompt: item.text || "",
messageId: props.message ? props.message : firstsendId.value,
};
formData.append("messageRequest", JSON.stringify(jsonObject));
formData.append("file", fileList.value[1] || []);
// 等待 getSessionJHistorys 函数完成
const res = await getSessionJHistorys(formData);
// 确保 id 和 messageId 在此处已更新
console.log(questionid.value, "Updated questionid.value");
console.log(firstsendId.value, "Updated firstsendId.value");
if (!props.message) {
emit("onLoad");
}
}, 100);
};
可以在 processChunk
函数内部明确地将状态更新放在 watch
之前。确保 id
和 messageId
的更新在 watch
触发之前完成。
const processChunk = (chunk: any) => {
if (paused.value === true) {
return;
}
// 数据处理逻辑...
if (answerSessions.length > 0) {
answerSessions.forEach((session) => {
const matches = session.match(answerSessionRegex);
if (matches) {
const sessionObject = {
id: parseInt(matches[1], 10),
messageId: BigInt(matches[2])
};
const serializedObj = JSON.stringify({
...sessionObject,
messageId: sessionObject.messageId.toString()
});
answerSessionList.push(serializedObj);
}
});
const jsonObject = JSON.parse(answerSessionList[0]);
// 确保 id 和 messageId 先更新
questionid.value = jsonObject.id;
messageIds.value = jsonObject.messageId;
firstsendId.value = jsonObject.messageId;
}
const filteredResults = results.filter((data) => !answerSessionRegex.test(data));
const sentence = filteredResults.join("");
questionList.value = sentence;
};
通过确保异步函数执行顺序和状态更新顺序,可以确保 watch
函数捕获到最新的数据变化。可以尝试将状态更新与异步操作分离,并确保状态更新完成后再触发 watch
。此外,也可以考虑使用 watchEffect
作为替代方法。