haizlin / fe-interview

前端面试每日 3+1,以面试题来驱动学习,提倡每日学习与思考,每天进步一点!每天早上5点纯手工发布面试题(死磕自己,愉悦大家),6000+道前端面试题全面覆盖,HTML/CSS/JavaScript/Vue/React/Nodejs/TypeScript/ECMAScritpt/Webpack/Jquery/小程序/软技能……
http://www.h-camel.com
MIT License
25.49k stars 3.26k forks source link

[软技能] 第1436天 前端并发多个相同的请求,如何控制只发一个? #5394

Open haizhilin2013 opened 1 year ago

haizhilin2013 commented 1 year ago

第1436天 前端并发多个相同的请求,如何控制只发一个?

3+1官网

我也要出题

ShihHsing commented 1 year ago

原生实现

为了控制并发请求,可以使用以下两种常见的方式:

防抖

防抖是指在一段时间内多次触发同一事件,只执行最后一次触发的操作。在前端中,可以利用定时器来实现防抖的效果。具体实现方法如下:

function debounce(func, delay) {
  let timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, arguments);
    }, delay);
  }
}

在发送请求的地方使用防抖函数,如下所示:

const sendRequest = debounce(() => {
  // 发送请求的代码
}, 500);

上述代码中,sendRequest 是一个防抖函数,它将在 500ms 后执行。如果在 500ms 内再次触发 sendRequest 函数,计时器会被重新启动,并且等待 500ms,以确保只有最后一次触发才会发送请求。

节流

节流是指在一段时间内只执行一次操作。与防抖不同的是,节流是指在一定的时间间隔内只执行一次操作。在前端中,可以使用定时器来实现节流的效果。具体实现方法如下:

function throttle(func, delay) {
  let timer;
  return function() {
    if (!timer) {
      timer = setTimeout(() => {
        func.apply(this, arguments);
        timer = null;
      }, delay);
    }
  }
}

在发送请求的地方使用节流函数,如下所示:

const sendRequest = throttle(() => {
  // 发送请求的代码
}, 500);

上述代码中,sendRequest 是一个节流函数,它将在 500ms 后执行。如果在 500ms 内再次触发 sendRequest 函数,由于计时器还没有结束,函数不会执行任何操作。只有当计时器结束后才会再次触发请求。

Vue + Axios

在 Vue 中使用 Axios 发送请求,可以使用 Axios 的 CancelToken 来取消重复的请求,从而实现并发多个相同的请求只发送一个的效果。

具体实现方法如下:

  1. 创建 CancelToken

首先,需要创建一个 CancelToken,用于取消请求。在 Vue 中,可以在组件的 data 中定义一个 cancelToken 对象:

data() {
  return {
    cancelToken: axios.CancelToken.source().token
  }
}
  1. 发送请求时使用 CancelToken

在发送请求时,需要将定义的 cancelToken 对象作为配置的 cancelToken 属性传递给 Axios:

axios.get(url, {
  cancelToken: this.cancelToken
}).then(response => {
  // 处理响应结果
}).catch(error => {
  // 处理请求错误
});
  1. 取消重复的请求

在发送新的请求之前,需要取消之前正在进行的相同请求。可以通过判断上一次请求的 CancelToken 和当前请求的 CancelToken 是否相同来实现:

if (this.lastRequestCancelToken) {
  this.lastRequestCancelToken.cancel('取消重复的请求');
}
this.lastRequestCancelToken = this.cancelToken;

上述代码中,lastRequestCancelToken 是用于保存上一次请求的 CancelToken 对象的变量。在发送新的请求之前,需要先取消之前正在进行的相同请求,并将当前的 CancelToken 对象赋值给 lastRequestCancelToken 变量。

完整的实现代码如下:

data() {
  return {
    cancelToken: axios.CancelToken.source().token,
    lastRequestCancelToken: null
  }
},
methods: {
  fetchData() {
    if (this.lastRequestCancelToken) {
      this.lastRequestCancelToken.cancel('取消重复的请求');
    }
    this.lastRequestCancelToken = this.cancelToken;
    axios.get(url, {
      cancelToken: this.cancelToken
    }).then(response => {
      // 处理响应结果
    }).catch(error => {
      // 处理请求错误
    });
  }
}

上述代码中,fetchData 是发送请求的方法,在方法中使用了 CancelToken 来控制并发多个相同的请求只发送一个。