Axios

简介: Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

Axios

image.png

1、了解Axios

(一)了解Axios

一、特点

  1. 在浏览器端能发送ajax请求
  2. 能在node.js中发送http请求
  3. 支持promise的相关操作(API)
  4. 请求和响应的拦截器(能在请求之前做一些准备工作,在响应回来后对响应的结果做一些处理)
  5. 对请求和响应的数据做转换
  6. 取消请求
  7. 自动将结果转换成json格式数据
  8. 保护作用阻止XSRF攻击

官方文档:http://axios-js.com/zh-cn/docs/index.html

GIthub:https://github.com/axios/axios

如果测试,可以使用这个进行配合使用:npm install -g json-server

官网:https://github.com/typicode/json-server

2、安装

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

$ npm install axios

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

$ bower install axios

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

$ yarn add axios

4 ) cdn导入:

<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.0.0-alpha.1/axios.js"></script>

3、基本使用

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>

其他使用:

基本使用

<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>

4、基本知识

  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>
  1. 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>

5、源码

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>

6、总结

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)(适配器)

扩展

Object.keys()的详解和用法

在实际开发中,我们有时需要知道对象的所有属性;
ES5 引入了Object.keys方法,成员是参数对象自身的(不含继承的)所有可遍历enumerable )属性的键名。

传入对象,返回属性名

var data={a:1,b:2,c:9,d:4,e:5};
    console.log(Object.keys(data));//["a", "b", "c", "d", "e"]
    Object.keys(data).map((key,item)=>{
        console.log(key,data[key]);//key=>属性名    data[key]=>属性值
});

传入字符串,返回索引

var str = 'ab1234';
console.log(Object.keys(obj));  //[0,1,2,3,4,5]

传入数组 返回索引

var arr = ["a", "b", "c"];
console.log(Object.keys(arr)); // console: ["0", "1", "2"]

构造函数 返回空数组或者属性名

function Pasta(name, age, gender) {
      this.name = name;
      this.age = age;
      this.gender = gender;
      this.toString = function () {
            return (this.name + ", " + this.age + ", " + this.gender);
    }
}

console.log(Object.keys(Pasta)); //console: []

var spaghetti = new Pasta("Tom", 20, "male");
console.log(Object.keys(spaghetti)); //console: ["name", "age", "gender", "toString"]

扩展

Object.values()

Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历( enumerable )属性的键值。

Object.entries()

Object.entries方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历( enumerable )属性的键值对数组。

相关文章
|
XML JSON 前端开发
Axios的特点
Axios的特点
74 0
|
3月前
|
JSON JavaScript 前端开发
axios浅析(一)
 axios 是一个轻量的 HTTP客户端 基于 XMLHttpRequest 服务来执行 HTTP 请求,支持丰富的配置,支持 Promise,支持浏览器端和 Node.js 端。自Vue2.0起,尤大宣布取消对 vue-resource 的官方推荐,转而推荐 axios。现在 axios 已经成为大部分 Vue 开发者的首选。
|
6月前
|
JSON 前端开发 JavaScript
axios的详细使用
axios的详细使用
179 1
|
6月前
|
XML 存储 JSON
Axios
Axios
55 0
|
6月前
|
JSON 前端开发 API
axios使用
axios使用
|
6月前
|
存储 设计模式 JSON
快速理解 Axios
快速理解 Axios
67 0
|
6月前
|
前端开发 JavaScript
Axios有哪些常用的方法?
Axios有哪些常用的方法?
72 0
axios详解
axios详解
85 0
|
JSON JavaScript 前端开发
axios的简单的使用
axios的简单的使用
63 0
|
JSON JavaScript 前端开发
axios是什么
axios是什么
167 1