React学习笔记 --- Axios的基本使用

934 阅读6分钟

一、网络请求的选择

  1. 传统的Ajax是基于XMLHttpRequest(XHR)

  2. jQuery-Ajax

  3. Fetch API

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

    • axios是目前前端使用非常广泛的网络请求库,包括Vue作者也是推荐在vue中使用axios;

    • 主要特点包括:在浏览器中发送 XMLHttpRequests 请求、在 node.js 中发送 http请求、支持 Promise API、拦截请求和 响应、转换请求和响应数据等等;

    • axios的全称是 ajax i/o system

二、 基本使用

这里使用httpbin.org来进行测试

get

// 一般在这个生命周期函数中发送请求
componentDidMount() {
  // 基本的get请求
  axios({ // => axios可以直接作为函数进行使用
    url: 'http://httpbin.org/get', // => 请求的地址
    params: {  // => 请求的参数,可以跟在地址的后边,但推荐直接写在这里
     name: 'Klaus',
     age: 23
    },
    method: 'get' // => 默认就是get请求,所以这个配置默认可以不写
  }).then( res => console.log(res) ) // 表明axios返回的是一个Promise对象
}
// 参数1:url路径
// 参数2:query参数对象
const res = await axios.get('http://httpbin.org/get', {
    name: 'Klaus',
    age: 23
})

console.log(res)

post

axios({
    url: 'http://httpbin.org/post',
    data: {
        name: 'Klaus',
        age: 23
    },
    method: 'post'
}).then(console.log) // 成功的时候会将res返回,这里传递的函数,正好需要一个打印的参数
// 此时其就会将res传入console中并进行执行该函数
// 参数1:url
// 参数2: params参数对象
// 参数3:配置对象
const res = await axios.post('http://httpbin.org/post', {
    name: 'Klaus',
    age:  23
})

console.log(res)`

axios支持的请求

  1. axios(config)
  2. axios.request(config)
  3. axios.get(url[, config])
  4. axios.delete(url[, config])
  5. axios.head(url[, config])
  6. axios.post(url[, data[, config]])
  7. axios.put(url[, data[, config]])
  8. axios.patch(url[, data[, config]])

axios的所有请求 本质上最后都会调用为axios.request方法

axios的源码中

function createInstance(defaultConfig) {
  var context = new Axios(defaultConfig);
  var instance = bind(Axios.prototype.request, context); // => 调用context.request,并接收到返回值

  // Copy axios.prototype to instance
  utils.extend(instance, Axios.prototype, context);

  // Copy context to instance
  utils.extend(instance, context);

  return instance; //=> 返回结果,所以调用axios方法的本质就是在调用axios原型上的request方法
}

// Create the default instance to be exported
var axios = createInstance(defaults); // => 所以默认导出的axios是一个函数
// => 如果是delete,get,head,options方法,其会将传入的配置和method以及url进行合并作为配置进行传递
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, config) {
    return this.request(mergeConfig(config || {}, {
      method: method,
      url: url
    }));
  };
});

// => 如果是post,put,patch方法,那么传入的参数回合method,url,data进行合并
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, data, config) {
    return this.request(mergeConfig(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
});

//=> 所以 最后在axios中无论是哪一种支持的方法,其最后的本质都是在调用axios原型上的request方法

补充

  1. axios.all
const request1 = axios.get('http://httpbin.org/get', {
    name: 'Klaus',
    age: 23
})

const request2 = axios.post('http://httpbin.org/post', {
    name: 'Klaus',
    age: 23
})

// 传入的多个请求的传入的参数格式为数组
axios.all([request1, request2]).then(console.log) //=> 输出的结果是以每一个请求的返回值组成的数组
// 所以如果需要直接获取传入的各个请求,可以使用数组的解构 [res1, res2] => console.log(res1, res2)

0mwul9.png

axios.all = function all(promises) {
  return Promise.all(promises); // axios.all 的本质就是 调用了 Promise.all 函数(其参数也是多个请求组成的数组)
}
  1. axios返回的数据不是单纯服务器返回的数据,而是基于服务器返回的数据基础上进行封装的数据

0mwNSH.png

三、 配置信息

在实际开发过程中,可能会存在需要在请求的时候需要重复配置的信息,例如baseURLheader,timeout

index.js

// 不要这么写,因为默认的axios.default中给多个配置项设置了默认值
// 如果这么写,就会将其指向一个新的对象,导致很多配置的默认选项不存在
// axios.defaults = {
//   baseURL: 'http://httpbin.org',
//   timeout: 5000
// }

// 需要单独修改属性
axios.defaults.baseURL = 'http://httpbin.org'
axios.defaults.timeout = 5000

// common 表示的是全部的请求方式
// axios.defaults.headers.common['token'] = 'asdsgfdsgfdg' // 所有的请求带上这个token
// axios.defaults.headers['token'] = 'asdadasdasf' // 这种写法和上面的写法是等价的
axios.defaults.headers.post['token'] = 'sdasdsarewr' // post请求的时候带上token,其余请求的时候不携带token0

App.js

const request1 = axios.get('/get', {
    name: 'Klaus',
    age: 23
})

四、 axios.create的基本使用

// 这就是所创建的一个新的axios对象
const _axios = axios.create({
  baseURL: 'http://httpbin.org',
  params: {
    name: 'Klaus',
    age: 23
  }
})
const res = await _axios.get('/get', {
    name: 'Klaus',
    age: 23
})

console.log(res) // 此时就是使用新创建的axios实例来发生网络请求

适用场景: 全局的接口都是调用http://www.wxf.com , 但是有一些接口需要请求http://www.klaus.com的时候,可以全局配置baseURL

http://www.wxf.com,可以新建一个axios对象,里面传入特殊的配置,使用这个新建的axios对象来处理发往http://www.klaus.com的请求

0mBbLR.png

新建的axios实例上,在传入配置项后,依旧可以使用defaults来修改新建的axios实例的配置项

此时请求内部的config配置 优先级 大于 defaults中配置 大于 创建实例时候create中传入的配置

// Factory for creating new instances
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};
//=> create的本质还是调用createInstance方法

五、 axios拦截器

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

  1. 发送网络请求时,在页面中添加一个loading组件作为动画;

  2. 某些网络请求要求用户必须登录,可以在请求中判断是否携带了token,没有携带token直接跳转到login页面;

  3. 对某些请求参数进行序列化;

响应拦截器:在响应结果中,结果被拦截;

  1. 响应拦截中可以对结果进行二次处理(比如服务器真正返回的数据其实是在response的data中);
  2. 对于错误信息进行判断,根据不同的状态进行不同的处理;
import axios from 'axios'

// 参数1:请求成功时候的callback callback参数: config 配置项信息对象
// 参数2:请求失败时候的callback callback参数: err 错误信息对象
axios.interceptors.request.use(config => {
  console.log('请求被拦截了')

  // 因为拦截,进行二次操作后,需要将其返回,以便于后续的操作可以获取到这个config
  return config
})

// 参数1:请求成功时候的callback callback参数: res 响应体对象
// 参数2:请求失败时候的callback callback参数: err 错误信息对象
axios.interceptors.response.use(res => res.data, err => {
  console.error(err)
  // 如果外部需要使用到错误对象的话,最好进行导出
  return err
})

补充

  1. 参数序列化
    • 将参数由对象转换为字符串的过程叫做序列化
    • 将参数由字符串转换为对象的过程叫做反序列化
    • 可以借助qs来进行操作