Axios 学习笔记--基础用法、并发请求、拦截器、封装

axios的特性

  • 支持Promise API
  • 可以拦截请求和响应 ( 比如拦截授权信息等等 )
  • 转换请求数据和响应数据 (加密解密敏感信息)
  • 取消请求
  • 自动转换JSON数据(一般http返回来的数据都是String类型,然后就要JSON.parse()做个手动转换,但是axios就会自动转换成json类型。)
  • 客户端支持防御XSRF

可以用于前端(客户端、浏览器)和nodejs后端

axios在vue中的使用

  1. npm i axios --save

  2. 在需要的页面上import axios from “axios”

  3. 使用:

    axios.get('/data.json').then(data => { // 用的本地json文件
     console.log(data.data.title)
    })
    

axios基础用法–get,post,put

axios请求方法: get,post, put, patch, delete

  • get 获取数据
  • post 提交数据(表单数据、文件 【图片、excel等】)
  • put : 更新/编辑数据 (所有数据推送到后端)
  • patch : 更新/编辑数据 (只有修改的 数据推送到后端)-

axios使用

create() {
	// 直接用get方法
	axios.get('/data.json', {
		params: { // 如果发送GET请求需要携带参数
			id: 12
		}
	}).then(res => console.log(res))
	// 用axios的config对象
	axios({
		method: 'get',
		url: '/data.json',
		params: {
			id: 12
		}
	}).then(res => {
		console.log(res)
	})
}
// 携带参数得到的最终url是 "http://localhost:8080/data.json?id=12"

Status Code: 200 // 访问正常 第一次访问
Status Code: 304 Not Modified // 不是第一次访问,数据没有修改,重定向,提高速度

post,put 方法

axios.post('url', {'请求数据'}, config) // 这是标准格式
// post 请求数据有两种形式:
// 1.  application/json
let applicData = {
	id: 12
}
axios.post('/post', applicData).then(res => console.log(res))
//或
axios({
	url: '/post',
	method: 'post',
	data: applicData
}).then(res=>{console.log(res)})

// 2.  form-data 表单提交(图片和文件上传)
let formData = new FormData()
for(let key in applicData){
	formData.append(key, applicData[key])
}
axios.post('/post', formData).then(
	res=>{
		console.log(res)
	}
)

浏览器F12-Network-post-Headers中:
Content-Type:application/json 或 multipart/form-data

delete 方法

axios.delete('/delete', {
	params: { // id=12 直接放在url上 as Query String Parameters
		id: 12
	}
}).then(res => console.log(res))

axios.delete('/delete', {
	data: {  // url上不出现id=12, 在Headers中as Request Payload
		id: 12
	}
}).then(res => console.log(res))

并发请求 all,spread

同时进行多个请求,并统一处理返回值,比如 好友列表和用户信息分别从两个接口请求。

axios.all([ // all里面是一个请求的数组
	axios.get('/data.json'),
	axios.get('/city.json')
]).then(// then里面要用spread方法
	axios.spread((dataRes, cityRes) => {
		console.log(dataRes, cityRes)
	})
)

创建axios实例

let instance = axios.create({
	baseURL: "http://localhost:8080", // 请求域名 基本地址
	timeout: 1000 // 超时时长设置 超过没response则401超时报错
})
instance.get('/data.json').then(res=>{
// /data.json是相对路径,发送请求时会自动拼接为baseURL+/data.json
	console.log(res)
})

axios的基本配置参数

axios.create({
	baseURL: "http://localhost:8080", // 请求域名 基本地址
	timeout: 1000, // 超时时长设置 超过没response则401超时报错
	url: '/data.json', // 请求路径
	method: 'post', // 请求方法
	header: {token}, // 请求头
	params:{}, // 请求参数 -- 拼接在url中
	data:{} // 请求参数--放在请求体中
})

axios配置类别

  1. 全局配置(优先级最低)-- 实际开发中很少用到
axios.defaults.timeout = 2000
axios.defaults.baseURL = 'http://localhost:8081'

全剧配置一般只配置这两个参数

  1. 实例配置(优先级中间)
let instance = axios.create();
instance.defaults.timeout = 2000; // 修改实例配置
  1. 请求配置(优先级最高)
instance.get('/data', {
	timeout: 2000
})

axios进阶方法-- 实例、配置、拦截器、取消请求

拦截器

在请求或响应在被处理前拦截它们 – 发起请求前和后端响应之后做一些处理
分为请求拦截器和响应拦截器
拦截器通常会给axios的实例设置,而不是全局axios设置,否则容易造成全局污染

// 请求拦截器
axios.interceptors.request.use(
	config => { // 第一个回调函数是配置函数
		// 在发送请求前需要做些什么 -- 修改配置或弹出内容等
		return config // 要记得返回设置好的config
	}, err=>{ // 第二个回调函数是错误函数
		// 在请求错误的时候做些什么
		return Promise.reject(err) // err会到axios.get().then(成功).catch(err)
	}
)
// 响应拦截器
axios.interceptors.response.use(
	res=> { // 第一个回调函数
		// 在请求成功对响应数据的处理
		return res
	}, err=>{ // 第二个回调函数
		// 响应错误做些什么
		return Promise.reject(err)
	}
)
// 取消拦截器 -- 不常用
let interceptors = axios.interceptors.request.use(config=>{
	config.headers={
		auth: true
	}
	return config
})
axios.interceptors.request.eject(interceptors)

// 实际例子 登陆状态 -- 后台返回token:‘’来判断权限,通常会放到header中
let instance = axios.create({})
instance.interceptors.request.use(
	config=>{
		config.headers.token = '' // 给header加token用来访问需要登陆的接口
		return config
	}
)
let instanceNotoken = axios.create({}) // 不加拦截器可以用来访问不需要登陆的接口

// 移动端开发 -- 注重用户体验,可以在请求的时候添加个等待的画面
let instance_phone = axios.create({})
instance_phone.interceptors.request.use(config=>{
	$('#modal').show() // 发送请求的时候显示弹窗
	return config
})
instance_phone.interceptors.response.use(res=>{
	$('#modal').hide() // 请求成功后隐藏弹窗
	return res
})

错误处理

请求发生错误时进行的处理 // 404接口未找到,401请求超时

axios.get(url)
.then() // 请求成功
.catch(err=>{ // 请求或响应失败的err都会进入到catch中
//在实际开发过程中,一般需要添加统一错误处理,而不是添加catch,否则每个接口一个catch会比较不好处理
})

// 统一添加错误处理
let instanceErr = axios.create({});
instanceErr.interceptors.request.use(
	config=>{
		//
		return config
	},err => {
		//请求错误 一般http状态码以4开头 401、 404
		return Promise.reject(err)
	}
)
instanceErr.interceptors.response.use(
	res=>{
		//
		return res
	},err => {
		//响应错误 一般http状态码以5开头500系统错误,502系统重启
		$('#modal').show()
		setTimeout(() => {
			$('#modal').hide()
		}, 2000)
		return Promise.reject(err)
	}
)
instanceErr.get('/data.json')
.then(res=>{...})
.catch(err=>{ // 如果是正常处理err,就不需要添加catch了,会用上面统一的err处理方式--modal展示和隐藏
	// But 如果这个接口的错误需要单独处理,就可以添加catch再重新写处理方式
})

在实际开发过程中,一般需要添加统一错误处理,而不是添加catch,否则每个接口一个catch会比较不好处理

取消请求

取消正在进行的http请求 – 用的很少

let source = axios.CancelToken.source();
axios.get('/data.json', { // 声明了一个带有取消请求token的请求
	cancelToken: source.token
}).then(res=>{
	console.log(res)
}).catch(err=>{console.log(err)})

// 发起请求后,取消请求:
source.cancel('cancel http') // message可不用

用到取消请求的情况:大型商城返回结果要 3-5秒,用户在此期间查询了下一类,上一个请求就用不到了,就可以取消请求

axios实际开发例子

获取通讯录列表,编辑、新增

在后端接口的文件夹中打开power shell,
npm i
node index.js //启动服务

安装vant plugin: npm i babel-plugin-import -D

axios进一步封装,在项目中的实际应用(比如授权信息放到header里进一步封装)

  1. 比如每一个请求都有一个catch,Toast… 造成代码冗余
  2. 带参数的请求,会造成每个请求的格式都不统一
  3. 请求的url每个都不同,不好管理–>放到统一的json文件中,请求的时候统一调用
// 第一步 封装每个页面中用到的请求到一个常量中
>>>src/service/contactApi.js // 封装请求url和方式
const CONTACT_API = {
  // 获取联系人列表
  getContactList: {
    method: 'get',
    url: '/contactList'
  }
}
export default CONTACT_API // 要记得export,因为别的地方要引入
// 第二步 封装请求方式到一个函数中-- 统一请求方式
>>>src/service/http.js
>import axios from 'axios'
import service from './contactApi'
import { Toast } from 'vant'

// service 循环遍历,输出不同的请求方法
let instance = axios.create({
  baseURL: 'http://localhost:9000/api',
  timeout: 1000
})
const Http = {}; // 包裹请求方法的容器

for (let key in service) {
  let api = service[key]; // 遍历的每个请求的url, method
  Http[key] = async (params, isFormdata=false, config={}) => { // 给形参设置初始值
    let url = api.url;
    let newParams = {};

    // 判断是否为form-data
    if(params && isFormdata) { // 如果有参数,并且是formData类型,则要把参数转换成formData类型
      newParams = new FormData();
      for(let k in params){
        newParams.append(k, params[k]); // append()方法是FormData数据类型添加内容的方法
      }
    }else { // 如果不是formData类型,就直接复制
      newParams = params;
    }

    // 不同请求的判断
    let response = {}; // 每个请求都需要一个返回值
    if(api.method === 'post' || api.method === 'put' || api.method === 'patch') {
      try{
        response = await instance[api.method](url, newParams, config);
      }catch(err){
        response = err;
      }
    }else if(api.method === 'delete' || api.method === 'get') {
      config.params = newParams;
      try{
        response = await instance[api.method](url, config);
      }catch(err){
        response = err;
      }
    }

    return response // 函数的最终的响应返回值
  }
}

// 拦截器
instance.interceptors.request.use(// 请求拦截器
  config => {
    // 请求前的操作
    Toast.loading({
      mask: false,
      duration: 0, // 默认是1,设为0是一直存在
      forbidClick: true, // 禁止点击
      message: 'Loading...'
    });
    return config
  }, err => {
    //请求错误
    Toast.clear(); // 把一直存在的loading去掉
    Toast('error')
  }
)

instance.interceptors.response.use(// 响应拦截器
  res => {
    // 请求成功
    Toast.clear(); // 请求成功先吧loading去掉
    return res.data // res里包含了很多东西,我们只用data(code...)
  }, err => {
    Toast.clear();
    Toast("响应错误...")
  }
)

export default Http
// 第三步 把Http挂载到Vue实例上

>>> main.js
import Http from './service/http'
Vue.prototype.$Http = Http // 就可以全局使用了,不需要每个页面都引入
// 第四步 页面上使用Http
>>> ContactList.vue
async onDelete (info) { // 删除联系人
	 let res = await this.$Http.delContactList(info);
	 if(res.code === 200){
	   Toast('删除成功'),
	   this.showEdit = false;
	   this.getList();
	 }
}

网络课程: https://www.imooc.com/learn/1152

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值