全部文章
工具笔记

让 AI 修异步搜索:旧请求晚到也不能盖住新结果

用取消与请求身份保护搜索界面。

资料核验2026.11.12 · HTTP 与 Fetch · 浏览器及服务端请求

用户先搜「笔记」,立刻改成「订阅」。第二个请求先返回,界面一瞬间是对的,几百毫秒后又被第一个请求的旧结果覆盖。响应顺序与发出顺序并不绑定。

交给编码助手的任务

让助手在浏览器测试里刻意延迟第一个搜索响应,第二个立即返回。要求结果、加载状态与错误提示都绑定当前请求,取消旧请求只作为节省开销的手段。

流程示意:发送旧关键词;新关键词先返回;丢弃旧结果

让当前关键词拥有最后决定权

每次查询生成一个请求序号。返回时只接收当前序号的结果,错误和加载状态也做同样判断。可以用 AbortController 取消上一轮 fetch,减少不需要的工作。超时则作为当前请求自己的错误处理。

测试故意让第一轮响应晚到。观察结果、加载提示和错误提示都属于第二个关键词。

如果取消旧请求,也别显示「搜索失败」。那次取消是页面主动做的,用户正在等的是下一次查询。

先准备一个对照样例

先搜「笔记」后搜「订阅」,把两个响应设置为固定的逆序。核对旧请求晚回时新结果仍留在屏幕上。再让旧请求返回错误,检查错误横幅不会覆盖当前已成功的关键词。

用这些结果验收

  • 第二个关键词先展示。
  • 第一个晚回后页面保持第二个结果。
  • 旧请求失败时也不覆盖当前结果。
  • 清空搜索按页面约定恢复。

审查时容易漏掉什么

如果实现只取消请求但没有身份检查,问它已经完成解析、即将提交状态的旧响应怎么处理。用固定的响应顺序让问题稳定出现,之后再看界面是否恢复。

用户中途清空搜索也会改变当前请求身份。给助手第三条场景:A 在等待,用户清空,A 稍后回来。检查列表保持初始状态,加载提示没有重新出现。避免通过延迟防抖把先后顺序问题掩盖掉。

示例只演示响应归属。若另外显示加载状态,结束加载前也要判断请求是否仍是当前请求。

let latest = 0;
async function search(keyword) {
  const request = ++latest;
  try {
    const results = await loadResults(keyword);
    if (request === latest) showResults(results);
  } catch (error) {
    if (request === latest) showError(error);
  }
}
function clearSearch() {
  latest++;
  restoreInitialList();
}

资料来源