前端限制搜索时的请求频率(请求竞态)

145 阅读4分钟
防抖(由于服务相应的顺序不一定是按顺序返回,可能会先搜的后返回)
节流(保留第一次请求不合适)
使用锁控制技术:确保一段时间内只能有一个请求。
let lock = false; // 初始化锁为未上锁状态 
const delay = 2000; // 延迟时间设置为2000毫秒(解锁时间) 
async function sendRequest() { 
    if (lock) { 
        console.log("请求已被锁定,等待前一个请求完成"); 
        return; 
    } 
    lock = true; // 上锁 
    try { 
        // 假设一个返回Promise类型的异步操作,例如fetch(), axios() 
        await new Promise(resolve => setTimeout(resolve, delay)); 
        console.log("Request sent and completed"); 
    } catch (error) { 
        console.error(error); 
    } finally { 
        setTimeout(() => lock = false, delay); // 一段时间后解锁,允许发送新的请求 
    } 
} 
// 测试这个限制 
sendRequest(); // 将发送请求 
sendRequest(); // 不会发送请求,因为上锁了
取消请求(有一定效果,因为这只是单方面的客户端取消操作)
  • 当你调用 XmlHttpRequest 的 abort 方法时,当前正在处理的请求确实会被立即取消,这点是无疑的。问题的关键在于,“取消” 是在客户端进行的,而不是在服务端。换句话说,abort 方法只能停止 XmlHttpRequest 继续发送或接收请求,但不能影响到服务端。具体来说,假设有以下几种情况:
      1. 如果在请求真正发送到服务器之前调用 abort,那么请求将不会发送出去,服务端也不会接到这个请求。
      1. 如果请求已经发送出去,但服务器还没有开始处理,这时候调用 abort,请求仍然会继续在网络上传输,直到达到服务器。此时,服务器可能开始处理这个请求,但因为客户端已经调用了 abort,所以客户端不会接收到任何来自服务器的响应。
      1. 如果请求已经发送出去,服务器也已经开始处理,这时候调用 abort,情况就更复杂了。请求仍然会在网络上继续传输,服务器也会继续处理这个请求。但同样的,因为客户端已经调用了 abort,所以客户端不会接收到任何来自服务器的响应。
  • 因此浏览器的network的cancell状态码请求并不能保证服务端一定会停止处理这个请求。当调用abort方法时,XmlHttpRequest会立即停止正在进行的网络活动,并将其状态重置。对于客户端来说,这个请求就已经被认为是“取消”了。然而,如果这个请求已经被发送到了服务端,那么服务端可能仍然会继续处理这个请求,因为服务端可能并未接收到任何取消请求的信息。换句话说,abort方法并不能保证服务端一定会知道客户端已经放弃了这个请求。这是一个非常基础的网络中处理请求和响应的难题,客户端和服务端的通信存在着一定的延迟和不可预见性。目前还没有一种取消策略能夠完全解决这个问题。因此,abort方法通常是用来提高客户端的性能和用户体验,而不能看作是一种确保服务端停止处理请求的可靠方式。理地处理服务端返回的错误信息等,以提升用户体验。 要让服务端终止正在处理的请求并不总是可行的。原因在于很多情况下,当请求已经发送到服务器并开始处理后,这个过程就无法再被中断。特别是对于那些执行时间长、需要进行大量计算或者涉及到数据库操作的请求,一旦开始就很难在中途停止。
  • 尽管如此,还是有一些策略可以被应用在某些特定的情况中,以减少无效请求对服务器的影响:
      1. 使用请求ID:每个请求都带有一个唯一的ID,服务器在接收到一个新的请求时会检查这个ID。如果发现服务器正在处理的请求与新请求的ID相同,在服务器资源允许的情况下,可以考虑将正在处理的请求停止,然后开始处理新的请求。
      1. 设置时间限制:可以对服务器端的请求处理设置一个时间限制,如果处理请求超过这个时限,那么就停止处理并返回一个错误或者超时的响应。
      1. 特定的处理机制:根据应用的特点,可以设计特定的处理机制。比如,如果应用是一个在线游戏,服务器可以设计一种机制,让玩家在发起新的活动前必须停止正在进行的活动。这就能有效地避免服务器进行无用功。
  • 虽然这些策略可能会有一定的效果,但是实际上要想完全避免服务器继续处理已经被取消的请求,目前仍然没有一种既可行又完全可靠的解决方案