搜索结果倒着更新:给请求加一个序号

举报
yd_275510632 发表于 2026/10/26 01:44:27 2026/10/26
【摘要】 搜索框快速输入时,后发请求可能先完成,旧响应随后覆盖新结果。本文用 80/20 毫秒的本地受控异步实验说明问题,并用递增序号只提交最后一次搜索结果,同时说明 AbortController 的边界。

搜索框快速输入时,后发请求不一定先完成。用户先输入“旧关键字”,很快又输入“新关键字”,两个异步任务同时存在;如果每个完成回调都直接更新界面,后完成的旧响应就可能覆盖新结果。Promise 本身没有失序,问题在于提交结果时没有确认它仍代表最后一次用户意图。

下面的实验不访问网络,用两个可控的本地异步请求复现逆序完成:旧关键字等待 80 毫秒,新关键字等待 20 毫秒。这里使用 async request,在函数内 await sleep 后直接 return 结果。

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function request(keyword, delay) {
  await sleep(delay);
  return { keyword, items: [`${keyword}-结果`] };
}

let displayed = '(空)';
let latestSequence = 0;

async function search(keyword, delay) {
  const sequence = ++latestSequence;
  const data = await request(keyword, delay);
  if (sequence !== latestSequence) return;
  displayed = data.items.join(',');
}

await Promise.all([
  search('旧关键字', 80),
  search('新关键字', 20),
]);
console.log(displayed); // 新关键字-结果

无保护版本中,新关键字先提交,旧关键字后提交,最终显示旧结果。解决办法是在每次发起搜索时递增 latestSequence,把序号保存到本次请求;响应准备提交前比较 sequence === latestSequence,只有相等才允许改变界面。实验中,新关键字是序号 2,旧关键字是序号 1,因此旧响应会被丢弃,最终仍显示新结果。

检查不应只包住成功列表,也要覆盖错误提示和 loading 结束等会改变界面的 UI 状态。序号表达的是最后一次用户意图,不判断服务器内容孰优,也不保证请求已经取消。

如果使用真实 fetch,可以在发起新请求时调用上一次 AbortController.abort(),并把新的 signal 传给 fetch,以减少旧请求的下载和解析工作。中止后的 fetch 可能以 AbortError 拒绝,应单独处理。但取消不是提交门禁:可能发生得太晚,响应可能已经到达,其他异步任务也未必支持 signal,更不能据此断言服务器端工作已撤回。因此可靠组合是“AbortController 减少浪费 + 序号检查保护 UI”。

本实验只证明本地异步完成顺序与提交策略的关系,不代表线上测速或部署行为。

AI 辅助说明

本文由 AI 辅助整理结构、编写最小实验和核对表述;脚本已在本地 Node.js 实际运行,代码未部署。

参考资料

MDN Web Docs — Fetch API https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API MDN Web Docs — AbortController https://developer.mozilla.org/en-US/docs/Web/API/AbortController

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。