如何中断发出去的http请求

3,481 阅读2分钟

前言

项目中遇到一个问题,在连续发送同一个请求时,如果第二次请求比第一次请求快,那么实际显示的是第二次请求的数据,这就会造成数据和我选择的内容不一致的问题。解决的方案:在后续发送请求时,判断之前的请求是否完成(同一个接口),如果未完成则立即取消,然后在发送新的请求。而前端常用的发送请求的方式无非是两种,一种是利用ajax封装请求的Axios,一种是利用H5新特性的Fetch进行请求,接下来我们针对这两种请求简述一下如何中断请求。

如何中断请求

Axios

  1. 想要中断Axios请求,就需要清楚Axios的底层调用的是什么。Axios基于ajax进行封装,底层调用的是XMLHttpRequest

  2. 中断Axios如果该请求已被发出,XMLHttpRequest.abort()方法将终止该请求,当一个请求被终止,它的readyState将被置为XMLHttpRequest.UNSENT(0),并且请求的status置为0。

  3. Axios内置CancelToken类,并且new时可以传入回调函数,回调函数接受一个参数cancel函数,CancelToken会把取消回调注入给参数callback,外部使用cancelCallback接收。

    1. CancelToken构造函数生成cancel函数

      async request() {
        try {
          if (typeof this.cancelCallback === 'function') {
              this.cancelCallback('请求中断')
              this.cancelCallback = null
          }
          const ret = await axios.get({
            data: {},
            cancelToken: new axios.CancelToken(callback => this.cancelCallback = callback)
          })
        } catch (error) {
          console.log(error)
        }
      }
      
    2. CancelToken.source()生成取消令牌token

      let cancelTokenSource = null;
      ​
      async request() {
        if (cancelTokenSource) {
            cancelTokenSource.cancel('请求中断')
            cancelTokenSource = null
        }
      ​
        const cancelToken = axios.CancelToken
        cancelTokenSource = cancelToken.source()
      ​
        try {
          const ret = await axios.get({
            cancelToken: cancelTokenSource.token,
            data: {}
          })
        } catch (error) {
          console.log(error)
        }
      }
      

Fetch

  1. Fetch是H5新添加的功能,在低版本是不支持的,比如: ie。为了中断Fetch请求跟随出现了AbortController一个控制器对象,允许你根据需要中止一个或者多个web请求。

  2. AbortController通过在请求中传入信号源,然后在需要中断请求的时候通过abort方法进行中断请求。

  3. AbortController类生成会返回abort中断请求的方法和signal中断请求匹配的信号源。

    // 1. 创建 abortController 对象
    const abortControllerObj = new AbortController()
    ​
    // 2. 创建信号源
    const signal = abortControllerObj.signal// 3. 使用
    const request = async () => {
      try {
        const ret = await fetch('/api/task/list', { signal })
        return ret
      } catch (error) {
        console.log(error)
      }
    }
    ​
    // 4. 中断
    abortControllerObj.abort()
    

结语

中断请求在开发需求的难免会碰到,如果在前期封装公司级请求中加入中断请求的功能也是进行了功能优化。大家可以学习一下,从而完善自己的请求封装函数。最后如果文章对你有用,请帮忙点赞,关注+评论。🙏🙏🙏