1. 竞态条件与搜索功能"闪烁"现象解析
1.1 问题现象:搜索结果为何会"闪烁"?
当用户在搜索框中快速输入"zhangsan"时,可能会出现一个奇怪的现象:搜索结果会先显示部分匹配的结果(如"李四"),然后又突然跳转到"张三"的结果。这种UI闪烁不仅影响用户体验,更严重的是可能导致用户看到错误的数据。
javascript复制function UserSearch() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
useEffect(() => {
if (!query) return;
async function search() {
const response = await fetch(`/api/users/search?q=${query}`);
const data = await response.json();
setResults(data); // 问题根源在这里
}
search();
}, [query]);
return (
<>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="搜索用户..."
/>
<ul>
{results.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</>
);
}
1.2 竞态条件的本质
竞态条件(Race Condition)是指多个操作竞争同一资源时,最终结果取决于它们执行的相对顺序,而这种顺序在运行时是不确定的。在前端数据获取场景中,主要表现为:
- 用户快速输入触发多个请求
- 请求返回顺序与发送顺序不一致
- 最后完成的请求不一定是最后发送的请求
- 过时的响应可能覆盖最新的响应
1.3 网络请求的不确定性
网络请求的返回顺序无法保证先进先出(FIFO),主要原因包括:
- 服务器处理差异:简单查询可能比复杂查询更快返回
- 网络路由差异:不同请求可能走不同的网络路径
- 缓存机制:某些请求可能命中缓存而快速返回
- 服务器负载:高负载时请求处理速度会变慢
2. 解决方案一:AbortController终止过时请求
2.1 AbortController工作原理
AbortController是现代浏览器提供的API,允许开发者中止fetch请求。其核心机制是:
- 创建AbortController实例
- 将controller.signal传递给fetch选项
- 调用controller.abort()终止关联的请求
javascript复制const controller = new AbortController();
fetch('/api/data', {
signal: controller.signal
});
// 中止请求
controller.abort();
2.2 完整实现方案
javascript复制function UserSearch() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!query.trim()) {
setResults([]);
return;
}
const controller = new AbortController();
let isMounted = true;
async function search() {
try {
setLoading(true);
const response = await fetch(
`/api/users/search?q=${encodeURIComponent(query)}`,
{
signal: controller.signal,
timeout:
解锁全文
加入我们的会员,获取最新、最热、最精彩的开发者技术内容