专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

解决前端竞态问题的乐观锁机制_乐观锁java

ins518 2025-09-28 00:14:15 技术文章 2 ℃ 0 评论

在前端开发中,搜索框的实时搜索功能是一个常见场景。用户输入文字时,每输入一个字符就发起搜索请求。但这里存在一个潜在的竞态问题:如果后发起的请求比先发起的请求更快返回,可能会导致错误的搜索结果显示。防抖能一定程度减少竞态问题的出现,但是无法杜绝。

竞态问题示例

假设用户快速输入"ab":

  1. 输入"a"时发起请求A
  2. 输入"b"时发起请求B
  3. 请求B先返回,显示"ab"的结果
  4. 请求A后返回,错误地覆盖为"a"的结果

乐观锁解决方案

我们可以借鉴后端乐观锁的机制来解决这个问题: #技术分享

复现竞态问题示例

加锁解决竞态问题示例

架构图

源码

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<title>竞态问题搜索示例</title>

<style>

# results {
        margin-top: 20px;
        border: 1px solid #ccc;
        padding: 10px;
        min-height: 100px;
      }
    </style>

</head>

<body>

<h1>竞态问题搜索示例</h1>

<input type="text" id="searchInput" placeholder="输入搜索内容..." />

<div id="results">搜索结果将显示在这里</div>

<script>

let requestVersion = 0

async function mockSearchApi(query) { const delay = 1000 - query.length * 200 await new Promise((resolve) => setTimeout(resolve, delay)) return `查询"${query}"的结果,延迟${delay}ms` }

async function raceSafeSearch(query) { const currentVersion = ++requestVersion

try { const response = await mockSearchApi(query) if (currentVersion === requestVersion) { document.getElementById('results').textContent = response console.log(`显示结果: ${response}`) } else { console.log(`忽略过时结果: ${response} (当前版本: ${requestVersion}, 请求版本: ${currentVersion})`) } } catch (error) { console.error('搜索出错:', error) } } document.getElementById('searchInput').addEventListener('input', (e) => { const query = e.target.value.trim() query && raceSafeSearch(query) }) </script>

</body>

</html>

实现原理

  1. 全局版本号requestVersion 是一个递增的计数器,每次发起新请求时递增
  2. 请求捕获 :每次发起请求前,保存当前的 currentVersion
  3. 响应验证 :当响应返回时,检查 currentVersion 是否等于最新的 requestVersion
  4. 如果相等,说明这是最新的请求结果,可以显示
  5. 如果不相等,说明已有更新的请求发出,忽略此结果
  6. 优化 :实际使用还可以加上防抖,减少不必要的请求丢弃。

总结

通过这种乐观锁机制,确保了只有最后一次请求的结果会被显示,有效解决了前端搜索中的竞态问题。这种方法简单高效,不需要复杂的状态管理,适用于大多数异步场景下的竞态问题处理。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表