Axios笔记(完结版)

本文详细介绍了Axios库的特性,包括在浏览器和Node.js中的使用、Promise支持、请求和响应拦截器、数据转换、取消请求等功能。通过示例展示了GET、POST、PUT、DELETE等HTTP请求的发送,并探讨了Axios的基本配置、实例创建和源码实现。同时,文章解释了请求和响应拦截器的工作原理,以及如何取消请求。此外,还模拟实现了Axios的部分核心功能,如请求发送过程和拦截器机制。
摘要由CSDN通过智能技术生成

目录

一、了解Axios

(一)了解Axios

(二)基本使用

(三)其他使用

二、基本知识

三、源码

(一)手动实现源码

(二)一些联系


一、了解Axios

(一)了解Axios

1. 特点

1)在浏览器端能发送ajax请求

2)能在node.js中发送http请求

3)支持promise的相关操作(API)

4)请求和响应的拦截器(能在请求之前做一些准备工作,在响应回来后对响应的结果做一些处理)

5)对请求和响应的数据做转换

6)取消请求

7)自动将结果转换成json格式数据

8)保护作用阻止XSRF攻击

2. 安装

1)使用npm(包管理工具)最后通过打包工具引入(项目使用)

$ npm install axios

2)使用bower(包管理工具)一般在页面使用script标签引入

$ bower install axios

3)使用yarn(包管理工具)(项目使用)

$ yarn add axios

4)使用jsDelivr CDN(学习阶段使用)

<script src=”https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js”/>

5)使用unpkg CDN(学习阶段使用)

<script src=”https://unpkg.com/axios/dist/axios.min.js”/>

3. axios配置 

(二)基本使用

引入

<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.min.js"></script>

1. axios发送请求方法

request、get、post、put、head、delete、options、patch等一系列http请求类型方法

2. axios请求响应结构

headers:响应头信息;

data:响应体的结果(服务器响应的结果,进行了json解析);

config:配置对象(包括了请求类型等等);

request:原生的ajax请求对象,也就是xhlhttprequest实例对象;

status:响应状态码,statusText:响应字符串

3.请求对象

文档:https://github.com/axios/axios

4. 基本使用(发送GET、POST、PUT、DELETE请求)

1)代码实现:

<div class="container">
      <h1 class="page-header">基本使用</h1>
      <button class="btn btn-primary">发送 GET 请求</button>
      <button class="btn btn-warning">发送 POST 请求</button>
      <button class="btn btn-success">发送 PUT 请求</button>
      <button class="btn btn-danger">发送 DELETE 请求</button>
</div>
    <script>
      const btns = document.querySelectorAll("button");

      //请求绑定
      btns[0].onclick = () => {
        //发送 AJAX 请求 利用axios发送
        //axios返回的是一个promise对象
        axios({
          //参数:请求类型
          method: "GET",
          //url
          url: "http://localhost:3000/posts/2",
          //还可以设置请求头信息等参数
        }).then((response) => {
          console.log(response);
        });
      };

      //POST请求 添加一篇新的文章
      btns[1].onclick = () => {
        //发送 AJAX 请求 利用axios发送
        //axios返回的是一个promise对象
        axios({
          //参数:请求类型
          method: "POST",
          //url
          url: "http://localhost:3000/posts",
          //还设置请求头
          data: {
            title: "sehunBBQ",
            author: "小彬",
          },
        }).then((response) => {
          console.log(response);
        });
      };

      //put请求更新数据
      btns[2].onclick = () => {
        //发送 AJAX 请求 利用axios发送
        //axios返回的是一个promise对象
        axios({
          //参数:请求类型
          method: "PUT",
          //url
          url: "http://localhost:3000/posts/3",
          //还设置请求头
          data: {
            title: "今天天气很好",
            author: "小彬",
          },
        }).then((response) => {
          console.log(response);
        });
      };

      //删除数据
      btns[3].onclick = () => {
        //发送 AJAX 请求 利用axios发送
        //axios返回的是一个promise对象
        axios({
          //参数:请求类型
          method: "DELETE",
          //url
          url: "http://localhost:3000/posts/3",
        }).then((response) => {
          console.log(response);
        });
      };
    </script>

(三)其他使用

<div class="container">
      <h1 class="page-header">基本使用</h1>
      <button class="btn btn-primary">发送 GET 请求</button>
      <button class="btn btn-warning">发送 POST 请求</button>
      <button class="btn btn-success">发送 PUT 请求</button>
      <button class="btn btn-danger">发送 DELETE 请求</button>
    </div>
    <script>
      const btns = document.querySelectorAll("button");

      //发送get请求
      btns[0].onclick = () => {
        //axios()方法发送
        axios
          .request({
            method: "GET",
            url: "http://localhost:3000/comments",
          })
          .then((response) => {
            console.log(response);
          });
      };

      //发送post请求
      btns[1].onclick = () => {
        //axios()方法发送
        axios
          .post("http://localhost:3000/comments", {
            body: "hello",
            postId: 2,
          })
          .then((response) => {
            console.log(response);
          });
      };
    </script>

二、基本知识

1. axios默认配置

<body>
    <div class="container">
        <h2 class="page-header">基本使用</h2>
        <button class="btn btn-primary"> 发送GET请求 </button>
        <button class="btn btn-warning" > 发送POST请求 </button>
        <button class="btn btn-success"> 发送 PUT 请求 </button>
        <button class="btn btn-danger"> 发送 DELETE 请求 </button>
    </div>
    <script>
        //获取按钮
        const btns = document.querySelectorAll('button');
        //默认配置
        axios.defaults.method = 'GET';//设置默认的请求类型为 GET
        axios.defaults.baseURL = 'http://localhost:3000';//设置基础 URL
        axios.defaults.params = {id:100};
        axios.defaults.timeout = 3000;//

        btns[0].onclick = function(){
            axios({
                url: '/posts'
            }).then(response => {
                console.log(response);
            })
        }

    </script>
</body>

2. axios实例对象

<body>
    <div class="container">
      <h1 class="page-header">基本使用</h1>
      <button class="btn btn-primary">发送 GET 请求</button>
      <button class="btn btn-warning">发送 POST 请求</button>
    </div>
  </body>
  <script>
    //获取按钮
    const btns = document.querySelectorAll("button");

    //创建实例对象
    //段子接口 https://api.apiopen.top/gegetJoke
    const passage = axios.create({
      baseURL: "https://api.apiopen.top",
      timeout: 2000,
    });

    const another = axios.create({
      baseURL: "https://b.cm",
      timeout: 2000,
    });
    //passage 与axios对象功能几乎是一样的
    //当做函数
    /*
    passage({
      url: "/getJoke",
    }).then((response) => {
      console.log(response);
    });
    */

    //借助封装好的方法
    passage.get("/getJoke").then((response) => {
      console.log(response.data);
    });
  </script>

3.axios拦截器:

请求拦截器(在发送请求前,使用函数对请求的参数和内容进行处理和检测,若请求有问题可直接进行拦截->取消,后进先执行=则后面的请求拦截器先执行)

响应拦截器(对响应的结果预处理,先进先执行=前面的响应拦截器先执行)

1)请求拦截器:

① 在真正发送请求前执行的回调函数

② 可以对请求进行检查或配置进行特定处理

③ 失败的回调函数,传递的默认是error

④ 成功的回调函数,传递的默认是config(也必须是)

2)响应拦截器

① 在请求得到响应后执行的回调函数

② 可以对响应数据进行特定处理

③ 成功的回调函数,传递的默认是response

④ 失败的回调函数,传递的默认是error

3)请求转换器:对请求头和请求体数据进行特定处理的函数

响应转换器:将响应体json字符串解析为js对象或数组的函数

4)代码

script>
      //设置一个请求拦截器,在请求拦截器中可以对请求参数进行修改
      //config:配置对象
      axios.interceptors.request.use(
        function (config) {
          console.log("请求拦截器 成功 1号");
          // config.headers.test = "I am only a header!";
          //修改 config 中的参数
          config.params = { a: 100 };
          return config;
        },
        (error) => {
          console.log("请求拦截器 失败 1号");
          return Promise.reject(error);
        }
      );

      axios.interceptors.request.use(
        function (config) {
          console.log("请求拦截器 成功 2号");
          // config.headers.test = "I am only a header!";
          //修改 config 中的参数
          config.timeout = 2000;
          return config;
        },
        (error) => {
          console.log("请求拦截器 失败 2号");
          return Promise.reject(error);
        }
      );

      //设置一个响应拦截器,可以对响应结果做一些处理
      axios.interceptors.response.use(
        function (response) {
          console.log("响应拦截器 成功 1号");
          return response;
        },
        function (error) {
          console.log("响应拦截器 失败 1号");
          return Promise.reject(error);
        }
      );

      //设置一个响应拦截器
      axios.interceptors.response.use(
        function (response) {
          console.log("响应拦截器 成功 2号");
          return response;
        },
        function (error) {
          console.log("响应拦截器 失败 2号");
          return Promise.reject(error);
        }
      );

      //发送请求
      axios({
        method: "GET",
        url: "http://localhost:3000/posts",
      })
        .then((response) => {
          console.log("自定义回调处理成功的结果");
          //console.log(response);
        })
        .catch((reason) => {
          console.log(reason);
        });
    </script>

4.取消请求:终端启动是输入json-server --watch db.json -d +时间(如 -d 2000)

  <body>
    <div class="container">
      <h1 class="page-header">axios取消请求</h1>
      <button class="btn btn-primary">发送请求</button>
      <button class="btn btn-warning">取消请求</button>
    </div>
  </body>
  <script>
    //获取按钮
    const btns = document.querySelectorAll("button");
    //2.声明一个全局变量
    let cancel = null;
    //发送请求
    btns[0].onclick = () => {
      //检测上一次请求是否已经完成
      if (cancel !== null) {
        //则代表上一次请求还未取消,故直接取消上一次请求
        cancel();
      }
      axios({
        method: "GET",
        url: "http://localhost:3000/posts",
        //1.添加配置对象的属性
        cancelToken: new axios.CancelToken((c) => {
          //3.将c的值赋值给cancel
          cancel = c;
        }),
      }).then((response) => {
        console.log(response);
        //当请求执行完后 将cancel进行初始化设置
        cancel = null;
      });
    };

    //取消请求
    btns[1].onclick = () => {
      cancel();
    };
  </script>

三、源码

(一)手动实现源码

1.axios发送请求

    <script>
      //构造函数
      function Axios(config) {
        //初始化
        this.defaults = config; //为了创建default默认属性
        this.interceptors = {
          request: {},
          response: {},
        };
      }
      //原型添加相关方法
      Axios.prototype.request = function (config) {
        console.log("发送AJAX请求,请求类型为" + config.method);
      };
      Axios.prototype.get = function (config) {
        return this.request({ method: "GET" }); //在内部调用了request方法
      };
      Axios.prototype.post = function (config) {
        return this.request({ method: "POST" });
      };

      //声明函数
      function createInstance(config) {
        //1.实例化一个对象
        let context = new Axios(config);
        //可使用Axios中的方法 如context.get(),但是不能当做函数使用
        //创建请求对象函数
        let instance = Axios.prototype.request.bind(context);
        //instance是一个函数,可以instance({}),此时instance不能 instance.get()
        //将 Axios.prototype对象中的方法添加到instance函数中
        Object.keys(Axios.prototype).forEach((element) => {
          instance[element] = Axios.prototype[element].bind(context);
        });
        //为 instance 函数对象添加属性 default 与 interceptors
        Object.keys(context).forEach((key) => {
          //进行赋值
          instance[key] = context[key];
        });
        return instance;
      }

      //创建对象
      let axios = createInstance({ method: "GET" });
      //发送请求
      axios.get();
    </script>

2.axios请求发送过程

    <script>
      //axios 发送请求 axios Axios.prototype.request bind
      //1.声明构造函数
      function Axios(config) {
        this.config = config;
      }
      Axios.prototype.request = (config) => {
        //发送请求
        //创建了一个promise对象
        let promise = Promise.resolve(config);
        //声明一个数组 undefine 作用:占位
        let chains = [dispatchRequest, undefined];
        //调用then方法指定回调
        let result = promise.then(chains[0], chains[1]);
        //返回promise结果
        return result;
      };

      //2.dispatchRequset函数
      function dispatchRequest(config) {
        //调用适配器发送请求
        return xhrAdapter(config).then(
          (response) => {
            //对响应结果进行处理
            return response;
          },
          (error) => {
            throw error;
          }
        );
      }

      //3.adapter适配器
      function xhrAdapter(config) {
        return new Promise((resolve, reject) => {
          //发送AJAX请求
          let xhr = new XMLHttpRequest();
          //初始化
          xhr.open(config.method, config.url);
          //发送
          xhr.send();
          //绑定事件
          xhr.onreadystatechange = () => {
            //判断成功的条件
            if (xhr.readyState === 4) {
              if (xhr.status >= 200 && xhr.status < 300) {
                //成功的状态
                resolve({
                  //配置对象
                  config: config,
                  //响应体
                  data: xhr.response,
                  //响应头
                  headers: xhr.getAllResponseHeaders(), //字符串
                  //xhr的请求对象
                  request: xhr,
                  //相应的状态码
                  status: xhr.status,
                  //响应状态字符串
                  statusText: xhr.statusText,
                });
              } else {
                //失败的状态
                reject(new Error("请求失败 失败的状态码为" + xhr.status));
              }
            }
          };
        });
      }

      //4.创建axios函数
      let axios = Axios.prototype.request.bind(null);

      axios({
        method: "GET",
        url: "http://localhost:3000/posts",
      }).then((response) => {
        console.log(response);
      });
    </script>

3.axios拦截器模拟实现

    <script>
      //构造函数
      function Axios(config) {
        this.config = config;
        this.interceptors = {
          request: new InterceptorManager(),
          response: new InterceptorManager(),
        };
      }
      //发送请求  难点与重点
      Axios.prototype.request = function (config) {
        //创建一个 promise 对象
        let promise = Promise.resolve(config);
        //创建一个数组
        const chains = [dispatchRequest, undefined];
        //处理拦截器
        //请求拦截器 将请求拦截器的回调 压入到 chains 的前面  request.handles = []
        this.interceptors.request.handlers.forEach((item) => {
          chains.unshift(item.fulfilled, item.rejected); //往数组前去添加
        });
        //响应拦截器
        this.interceptors.response.handlers.forEach((item) => {
          chains.push(item.fulfilled, item.rejected); //往数组后添加
        });

        // console.log(chains);
        //遍历
        while (chains.length > 0) {
          promise = promise.then(chains.shift(), chains.shift());
        }

        return promise;
      };

      //发送请求
      function dispatchRequest(config) {
        //返回一个promise 队形
        return new Promise((resolve, reject) => {
          resolve({
            status: 200,
            statusText: "OK",
          });
        });
      }

      //创建实例
      let context = new Axios({});
      //创建axios函数
      let axios = Axios.prototype.request.bind(context);
      //将 context 属性 config interceptors 添加至 axios 函数对象身上
      Object.keys(context).forEach((key) => {
        axios[key] = context[key];
      });

      //拦截器管理器构造函数
      function InterceptorManager() {
        this.handlers = [];
      }
      InterceptorManager.prototype.use = function (fulfilled, rejected) {
        this.handlers.push({
          fulfilled,
          rejected,
        });
      };

      //以下为功能测试代码
      // 设置请求拦截器  config 配置对象
      axios.interceptors.request.use(
        function one(config) {
          console.log("请求拦截器 成功 - 1号");
          return config;
        },
        function one(error) {
          console.log("请求拦截器 失败 - 1号");
          return Promise.reject(error);
        }
      );

      axios.interceptors.request.use(
        function two(config) {
          console.log("请求拦截器 成功 - 2号");
          return config;
        },
        function two(error) {
          console.log("请求拦截器 失败 - 2号");
          return Promise.reject(error);
        }
      );

      // 设置响应拦截器
      axios.interceptors.response.use(
        function (response) {
          console.log("响应拦截器 成功 1号");
          return response;
        },
        function (error) {
          console.log("响应拦截器 失败 1号");
          return Promise.reject(error);
        }
      );

      axios.interceptors.response.use(
        function (response) {
          console.log("响应拦截器 成功 2号");
          return response;
        },
        function (error) {
          console.log("响应拦截器 失败 2号");
          return Promise.reject(error);
        }
      );

      //发送请求
      axios({
        method: "GET",
        url: "http://localhost:3000/posts",
      }).then((response) => {
        console.log(response);
      });
    </script>

4.axios取消请求

  <body>
    <div class="container">
      <h1 class="page-header">axios取消请求</h1>
      <button class="btn btn-primary">发送请求</button>
      <button class="btn btn-warning">取消请求</button>
    </div>
  </body>
  <script>
    //构造函数
    function Axios(config) {
      this.config = config;
    }
    //原型 request 方法
    Axios.prototype.request = function (config) {
      return dispatchRequest(config);
    };
    //dispatchRequest 函数
    function dispatchRequest(config) {
      return xhrAdapter(config);
    }
    //xhrAdapter
    function xhrAdapter(config) {
      //发送 AJAX 请求
      return new Promise((resolve, reject) => {
        //实例化对象
        const xhr = new XMLHttpRequest();
        //初始化
        xhr.open(config.method, config.url);
        //发送
        xhr.send();
        //处理结果
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
            //判断结果
            if (xhr.status >= 200 && xhr.status < 300) {
              //设置为成功的状态
              resolve({
                status: xhr.status,
                statusText: xhr.statusText,
              });
            } else {
              reject(new Error("请求失败"));
            }
          }
        };
        //关于取消请求的处理
        if (config.cancelToken) {
          //对 cancelToken 对象身上的 promise 对象指定成功的回调
          config.cancelToken.promise.then((value) => {
            xhr.abort();
            //将整体结果设置为失败
            cancel = null;
            reject(new Error("请求已经被取消"));
          });
        }
      });
    }

    //创建 axios 函数
    const context = new Axios({});
    const axios = Axios.prototype.request.bind(context);

    //CancelToken 构造函数
    function CancelToken(executor) {
      //声明一个变量
      var resolvePromise;
      //为实例对象添加属性
      this.promise = new Promise((resolve) => {
        //将 resolve 赋值给 resolvePromise
        resolvePromise = resolve;
      });
      //调用 executor 函数
      executor(function () {
        //执行 resolvePromise 函数
        resolvePromise();
      });
    }

    //获取按钮 以上为模拟实现的代码
    const btns = document.querySelectorAll("button");
    //2.声明全局变量
    let cancel = null;
    //发送请求
    btns[0].onclick = function () {
      //检测上一次的请求是否已经完成
      if (cancel !== null) {
        //取消上一次的请求
        cancel();
      }

      //创建 cancelToken 的值
      let cancelToken = new CancelToken(function (c) {
        cancel = c;
      });

      axios({
        method: "GET",
        url: "http://localhost:3000/posts",
        //1. 添加配置对象的属性
        cancelToken: cancelToken,
      }).then((response) => {
        console.log(response);
        //将 cancel 的值初始化
        cancel = null;
      });
    };

    //绑定第二个事件取消请求
    btns[1].onclick = function () {
      cancel();
    };
  </script>

(二)一些联系

1.axios和Axios的关系

1)从语法上来说:axios不是Axios的实例

2)从功能上来说:axios是Axios的实例;(因为axios拥有Axios实例对象上的方法);

3)axios是Axios.prototype.request函数bind()返回的函数;

4)axios作为对象有Axios原型对象上的所有方法,有Axios对象上的所有属性;

2.instance与axios的区别

1)相同:

① 都是一个能发任意请求的函数:request(config);

② 都有发特定请求的各种方法:get()/post()/put()/delete();

③ 都有默认配置和拦截器属性:defaults/interceptors;

2)不同:

① 默认配置可能不一样;

② instance不具备axios后面添加的一些方法:creat()/CancelToken()/all();

3.axios运行的整体流程

request(config) -> dispatchRequest(config) -> xhrAdapter(config)(适配器)

#END(详细见B站尚硅谷)

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值