axios.create(config)

  1. 根据指定配置创建一个新的 axios, 也就就每个新 axios 都有自己的配置
  2. 新 axios 只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的
  3. 为什么要设计这个语法?
    (1) 需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一
    样, 如何处理
    (2) 解决: 创建 2 个新 axios, 每个都有自己特有的配置, 分别应用到不同要
    求的接口请求中
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>axios.create()</title>
</head>
<body>
  <!-- 
  1). axios.create(config)
    a. 根据指定配置创建一个新的axios, 也就就每个新axios都有自己的配置
    b. 新axios只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的
    c. 为什么要设计这个语法?
      需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一样, 如何处理
      解决: 创建2个新axios, 每个都有自己特有的配置, 分别应用到不同要求的接口请求中
  -->
  <script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
  <script>
    axios.defaults.baseURL = 'http://localhost:3000'

    // 使用axios发请求
    axios({
      url: '/posts' // 请求3000
    })

    // axios({
    //   url: '/xxx' // 请求4000
    // })

    const instance = axios.create({
      baseURL: 'http://localhost:4000'
    })

    // 使用instance发请求
    // instance({
    //   url: '/xxx'  // 请求4000
    // })
    instance.get('/xxx')
  </script>
</body>
</html>

拦截器函数

对request拦截器采用unshift(堆栈)
request.hanlders.forEach(item=>chains.unshift(item))
对response拦截器采用push(队列)
response.hanlders.forEach(item=>chains.push(item))

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>axios的处理链流程</title>
</head>
<body>
  
  <script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
  <script>
    /* 
    requestInterceptors: [{fulfilled1(){}, rejected1(){}}, {fulfilled2(){}, rejected2(){}}]
    responseInterceptors: [{fulfilled11(){}, rejected11(){}}, {fulfilled22(){}, rejected22(){}}]
    chain: [
      fulfilled2, rejected2, fulfilled1, rejected1, 
      dispatchReqeust, undefined, 
      fulfilled11, rejected11, fulfilled22, rejected22
    
    ]
    promise链回调: config 
                  => (fulfilled2, rejected2) => (fulfilled1, rejected1)   // 请求拦截器处理
                  => (dispatchReqeust, undefined) // 发请求
                  => (fulfilled11, rejected11) => (fulfilled22, rejected22) // 响应拦截器处理
                  => (onResolved, onRejected) // axios发请求回调处理
    */

    // 添加请求拦截器(回调函数)
    axios.interceptors.request.use(
      config => {
        console.log('request interceptor1 onResolved()')
        return config
      },
      error => {
        console.log('request interceptor1 onRejected()')
        return Promise.reject(error);
      }
    )
    axios.interceptors.request.use(
      config => {
        console.log('request interceptor2 onResolved()')
        return config
      },
      error => {
        console.log('request interceptor2 onRejected()')
        return Promise.reject(error);
      }
    )
    // 添加响应拦截器
    axios.interceptors.response.use(
      response => {
        console.log('response interceptor1 onResolved()')
        return response
      },
      function (error) {
        console.log('response interceptor1 onRejected()')
        return Promise.reject(error);
      }
    )
    axios.interceptors.response.use(
      response => {
        console.log('response interceptor2 onResolved()')
        return response
      },
      function (error) {
        console.log('response interceptor2 onRejected()')
        return Promise.reject(error);
      }
    )

    axios.get('http://localhost:3000/posts')
      .then(response => {
        console.log('data', response.data)
      })
      .catch(error => {
        console.log('error', error.message)
      })

    /* axios.get('http://localhost:/posts2')
      .then(response => {
        console.log('data', response.data)
      })
      .catch(error => {
        console.log('error', error.message)
      }) 
    */
  </script>
</body>
</html>
  1. 说明: 调用 axios()并不是立即发送 ajax 请求, 而是需要经历一个较长的流程
  2. 流程: 请求拦截器2 => 请求拦截器1 => 发ajax请求 => 响应拦截器1 => 响
    应拦截器 2 => 请求的回调
  3. 注意: 此流程是通过 promise 串连起来的, 请求拦截器传递的是 config, 响应
    拦截器传递的是 response

取消请求

  1. 基本流程
    配置 cancelToken 对象
    缓存用于取消请求的 cancel 函数
    在后面特定时机调用 cancel 函数取消请求
    在错误回调中判断如果 error 是 cancel, 做相应处理
  2. 实现功能
    点击按钮, 取消某个正在请求中的请求
    在请求一个接口前, 取消前面一个未完成的请求

基本代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>取消请求</title>
</head>
<body>
  <button onclick="getProducts1()">获取商品列表1</button><br>
  <button onclick="getProducts2()">获取商品列表2</button><br>
  <button onclick="cancelReq()">取消请求</button><br>

  <script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
  <script>
    let cancel  // 用于保存取消请求的函数
    function getProducts1() {
      axios({
        url: 'http://localhost:4000/products1',
        cancelToken: new axios.CancelToken((c) => { // c是用于取消当前请求的函数
          // 保存取消函数, 用于之后可能需要取消当前请求
          cancel = c
        })
      }).then(
        response => {
          cancel = null
          console.log('请求1成功了', response.data)
        },
        error => {
          cancel = null
          console.log('请求1失败了', error.message, error)
        }
      )
    }

    function getProducts2() {
      axios({
        url: 'http://localhost:4000/products2'
      }).then(
        response => {
          console.log('请求2成功了', response.data)
        },
        error => {
          cancel = null
          console.log('请求2失败了', error.message)
        }
      )
    }

    function cancelReq() {
      // alert('取消请求')
      // 执行取消请求的函数
      if (typeof cancel === 'function') {
        cancel('强制取消请求')
      } else {
        console.log('没有可取消的请求')
      }
    }
  </script>
</body>
</html>

在请求一个接口前, 取消前面一个未完成的请求:

 function getProducts1() {
      // 在准备发请求前, 取消未完成的请求
      if (typeof cancel==='function') {
        cancel('取消请求')
      }
      axios({
        url: 'http://localhost:4000/products1',
        cancelToken: new axios.CancelToken((c) => { // c是用于取消当前请求的函数
          // 保存取消函数, 用于之后可能需要取消当前请求
          cancel = c
        })
      }).then(
        response => {
          cancel = null
          console.log('请求1成功了', response.data)
        },
        error => {
          if (axios.isCancel(error)) {
            // cancel = null
            // 若不用这个,如果点三次第一个函数,会导致后面的第2个不能被取消,
            // 因为第一个函数的error回调函数把cancel=null,此时正在执行第二个函数,
            // 最后导致点击第三个函数时,判断的cancel=null,使得不能取消掉之前第二个函数
            console.log('请求1取消的错误', error.message)
          } else { // 请求出错了
            cancel = null
            console.log('请求1失败了', error.message)
          }
        }
      )
    }

使用拦截器优化代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>取消请求</title>
</head>
<body>
  <button onclick="getProducts1()">获取商品列表1</button><br>
  <button onclick="getProducts2()">获取商品列表2</button><br>
  <button onclick="cancelReq()">取消请求</button><br>

  <script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
  <script>

    // 添加请求拦截器
    axios.interceptors.request.use((config) => {
      // 在准备发请求前, 取消未完成的请求
      if (typeof cancel==='function') {
          cancel('取消请求')
      }
      // 添加一个cancelToken的配置
      config.cancelToken = new axios.CancelToken((c) => { // c是用于取消当前请求的函数
        // 保存取消函数, 用于之后可能需要取消当前请求
        cancel = c
      })

      return config
    })

    // 添加响应拦截器
    axios.interceptors.response.use(
      response => {
        cancel = null
        return response
      },
      error => {
        if (axios.isCancel(error)) {// 取消请求的错误
          // cancel = null
          console.log('请求取消的错误', error.message) // 做相应处理
          // 中断promise链接
          return new Promise(() => {})
        } else { // 请求出错了
          cancel = null
          // 将错误向下传递
          // throw error
          return Promise.reject(error)
        }
      }
    )


    let cancel  // 用于保存取消请求的函数
    function getProducts1() {
      axios({
        url: 'http://localhost:4000/products1',
      }).then(
        response => {
          console.log('请求1成功了', response.data)
        },
        error => {// 只用处理请求失败的情况, 取消请求的错误的不用
          console.log('请求1失败了', error.message)          
        }
      )
    }

    function getProducts2() {

      axios({
        url: 'http://localhost:4000/products2',
      }).then(
        response => {
          console.log('请求2成功了', response.data)
        },
        error => {
          console.log('请求2失败了', error.message)
        }
      )
    }

    function cancelReq() {
      // alert('取消请求')
      // 执行取消请求的函数
      if (typeof cancel === 'function') {
        cancel('强制取消请求')
      } else {
        console.log('没有可取消的请求')
      }
    }
  </script>
</body>
</html>
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐