const c = new AbortController();
fetch(url, { signal: c.signal });
return () => c.abort();

快速点三个商品,详情页先显示第三个,一秒后又被第一个的响应盖回去,控制台看不到任何报错,只能靠时间点判断。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:先发出的请求可能后返回,回调没有校验这次响应是否已经过期,直接 setState 覆盖了最新一条,切换越快越容易撞上这个顺序问题。

「请求竞态覆盖」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。监控和日志的时间要对上,时区不一致会多绕很大一圈。

临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。

处理上按这个顺序:用 AbortController 取消上一个还没回来的请求,只保留最后一次;给每次请求编号,回来时丢掉过期的那一份响应;把请求放进 watch 的 cleanup 里统一收尾,卸载时一并取消。

确认没问题再收工,连续切换后页面只保留最后一次点击的数据,旧响应回来也不覆盖。

作者 9823189