1.前端网络请求的选择

目前前端中发送网络请求的方式有很多种:

选择一: 传统的 Ajax 是基于 XMLHttpRequest

为什么不用它呢?

  • 非常好解释, 配置和调用方式等非常混乱
  • 编码起来看起来就非常蛋疼
  • 所以真实开发中很少直接使用, 而是使用jQuery-Ajax

选择二:在前面的学习中, 我们经常会使用jQuery-Ajax

  • 相对于传统的Ajax非常好用.

为什么不选择它呢?

  • jQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务)
  • 基于原生的XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案
  • 尽管JQuery对我们前端的开发工作曾有着深远的影响,但是的确正在推出历史舞台;

选择三: Fetch API

选择或者不选择它?

  • Fetch是AJAX的替换方案,基于Promise设计,很好的进行了关注分离,有很大一批人喜欢使用fetch进行项目开发;
  • 但是Fetch的缺点也很明显,首先需要明确的是Fetch是一个 low-level(底层)的API,没有帮助你封装好各种各样的功能和实现;
  • 比如发送网络请求需要自己来配置Header的Content-Type,不会默认携带cookie等;
  • 比如错误处理相对麻烦(只有网络错误才会reject,HTTP状态码404或者500不会被标记为reject)
  • 比如不支持取消一个请求,不能查看一个请求的进度等等;
  • MDN Fetch学习地址:https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch

选择四:axios

  • axios是目前前端使用非常广泛的网络请求库,包括Vue作者也是推荐在vue中使用axios;
  • 主要特点包括:在浏览器中发送 XMLHttpRequests 请求、在 node.js 中发送 http请求、支持 Promise API、拦截请求和响应、转换请求和响应数据等等;

2.axios的基本使用

  • axios(config)
  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

如何发送请求呢?可以使用httpbin.org这个网站来测试。

安装:yarn add axios

axios发送请求:

  • 直接通过axios函数发送请求
  • 发送get请求
  • 发送post请求
  • 多个请求的合并
  • 使用async、await发送请求

axios函数、get、post请求本质上都是request请求

import React, { PureComponent } from 'react'
import axios from "axios"

export default class App extends PureComponent {
  async componentDidMount() {

    // 1.发送网络请求的基本操作
    // axios({
    //   // 不写请求方法默认就是get
    //   url: "https://httpbin.org/get",
    //   params: { name: "Quan", age: 17 }
    // }).then(ret => {
    //   console.log(ret);
    // }).catch(err => {
    //   console.log(err);
    // })

    // axios({
    //   url: "https://httpbin.org/post",
    //   data: { name: "Quan", age: 18 },
    //   method: "post"
    // }).then(ret => {
    //   console.log(ret);
    // }).catch(err => {
    //   console.log(err);
    // })

    // 2.发送get/post请求
    // axios.get("https://httpbin.org/get", {
    //   params: {
    //     name: "quan",
    //     height: 1.8
    //   }
    // }).then(ret => {
    //   console.log(ret);
    // }).catch(err => {
    //   console.log(err);
    // })

    // axios.post("https://httpbin.org/post", {
    //   User: "QuanMou",
    //   password: 123456
    // }).then(ret => {
    //   console.log(ret);
    // }).catch(err => {
    //   console.log(err);
    // })

    // 3.简单阅读一下axios的e部分源码

    // 4.除了promise的ApI之外还有一种方法比较常用:async await
    // const ret = await axios({ url: "https://httpbin.org/get", params: { name: "quan" } });
    // console.log(ret);

    // 5.axios.all 并发请求,在拿到两个数据之后
    const ret1 = await axios({ url: "https://httpbin.org/get", params: { name: "quan" } });
    const ret2 = await axios({ url: "https://httpbin.org/post", data: { name: "quan" }, method: "post" });
    axios.all([ret1, ret2]).then(ret => {
      console.log(ret);
    })
  }
  render() {
    return (
      <div>
        app
      </div>
    )
  }
}

3.axios的配置信息

如果你只是向一个服务器发请求,可以全局配置一些默认信息。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'

import axios from "axios"

// 6.默认配置
axios.defaults.baseURL = "https://httpbin.org"
axios.defaults.headers.common['Authorization'] = "xxx";
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.timeout = 4000;

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

如果你要向多个服务器发送请求,可以创建不同的实例:

// 7.自定义实例
    const instance1 = axios.create({
      // 这个实例的配置
      baseURL: "https://baidu.com",
      timeout: 4000
    })

    const instance2 = axios.create({
      // 这个实例的配置
      baseURL: "https://httpbin.org",
      timeout: 4000
    })
    // instance1的默认配置
    axios.defaults.headers.common['Authorization'] = "xxx";

    instance2.get('/get', {
      params: { name: "hhh" }
    }).then(ret => {
      console.log(ret);
    })

3.axios拦截器

axios库有一个非常好用的特性是可以添加拦截器:

3.1请求拦截器:

在发送请求时,请求被拦截;

  • 发送网络请求时,在页面中添加一个loading组件作为动画;
  • 某些网络请求要求用户必须登录,可以在请求中判断是否携带了token,没有携带token直接跳转到login页面;
  • 对某些请求参数进行序列化;
  • 注意最后一定要return 出去
    // 8.拦截器
    axios({
      url: "https://httpbin.org/get",
      params: {
        name: "coder",
        age: 18
      }
    })
    // 请求拦截
    axios.interceptors.request.use(config => {
      console.log("请求拦截");
      return config;
    }, err => {

    })
    axios.interceptors.response.use(response => {
      console.log("响应拦截");
      return response;
    }, err => {

    })

4.对axios进行封装

为什么要二次封装?

  • 默认情况下我们是可以直接使用axios来进行开发的;
  • 但是我们考虑一个问题,假如有100多处中都直接依赖axios,突然间有一天axios出现了重大bug,并且该库已经不再维护,这个时候你如何处理呢?
  • 大多数情况下我们会寻找一个新的网络请求库或者自己进行二次封装;
  • 但是有100多处都依赖了axios,方便我们进行修改吗?我们所有依赖axios库的地方都需要进行修改;

封装代码:

我可能会建个文件夹里面是对axios的二次封装,有两个文件:request.js config.js

config.js:

// 如果我们在开发环境和生产环境用的都是不同的接口:
const productionURL = "https.xxxx.cn"
const developURl = "https.xxxxx.com"

// node里有个方法可以判断是生产环境还是开发环境
export const BaseUrl = process.env.NODE_ENV === "development" ? developURl : productionURL;
export const TimeOut = 5000;

request.js:

import axios from "axios"
import { BaseUrl, TimeOut } from "./config"
const instance = axios.create({
  baseURL: BaseUrl,
  timeout: TimeOut
})

instance.interceptors.request.use(config => {
  console.log('请求拦截');
  return config;
}, err => {
  console.log('错误');
})

instance.interceptors.response.use(response => {
  console.log('响应拦截');
}, err => {
  console.log('err里面有个response。可以根据里面的内容做些操作');
})

export default instance;
文章目录