axios
前言
使用 vue 开发时,频繁使用到了 axios 这个网络请求库,这里对其做一个发起请求时携带参数方式的小结。
一、基本使用
1.1. GET 请求
注意:GET 请求无请求体,可以是可以有请求体 body 的,但是不建议带。
为什么不建议带请求体?
:::details 由文心大模型 3.5 生成
在 HTTP 协议中,GET 请求通常用于请求数据,而 POST 请求则通常用于提交数据。这是因为 GET 和 POST 请求在语义和使用上有一些不同:
- 语义上的不同:
- GET 请求:通常用于请求数据,它的语义是“获取”或“查询”。浏览器会把 GET 请求的结果(响应体)直接展示给用户。
- POST 请求:通常用于提交数据,它的语义是“提交”或“更新”。POST 请求的结果通常是一个操作的结果,而不是直接展示给用户的数据。
- 请求体的处理:
- GET 请求:虽然 GET 请求可以包含请求体(body),但大多数 HTTP 客户端和服务器在处理 GET 请求时都会忽略请求体。这是因为 GET 请求的设计初衷就是为了从服务器获取数据,而不是提交数据。GET 请求的查询参数应该放在 URL 的查询字符串中,而不是请求体中。
- POST 请求:POST 请求通常包含请求体,用于提交数据给服务器。服务器会处理 POST 请求的请求体来获取提交的数据。
- 缓存和书签:
- GET 请求是幂等的和安全的,这意味着多次执行相同的 GET 请求应该得到相同的结果,并且不会改变服务器上的任何数据。因此,浏览器通常会对 GET 请求进行缓存。如果 GET 请求包含请求体,这可能会导致缓存行为不一致或不可预测。
- 由于 GET 请求的 URL 通常会被浏览器记录在历史记录或书签中,如果 URL 中包含了敏感信息(这些信息通常应该放在请求体中),那么这些信息可能会被泄露。
- URL 长度限制:
- 浏览器和服务器通常对 URL 的长度有一定的限制。如果 GET 请求包含大量的数据在 URL 中(通过查询参数),这可能会导致 URL 超过长度限制。
- 安全性:
- 将敏感信息(如密码、私钥等)放在 GET 请求的 URL 中是不安全的,因为这些信息可能会被记录在浏览器历史、服务器日志或代理缓存中。这些信息应该通过 POST 请求放在请求体中,并使用适当的加密和身份验证机制来保护。
综上所述,虽然技术上 GET 请求可以包含请求体,但出于上述原因,通常不建议在 GET 请求中包含请求体。在实际开发中,应该根据请求的性质和目的选择合适的 HTTP 方法,并遵循相应的最佳实践。
:::
1.1.1. 使用 GET 方式进行无参请求
接口
@GetMapping("/get/getAll") public ResResult getAllUser(){ List list = userService.list(); return ResResult.okResult(list); }
请求
axios({ url:'http://localhost:8080/get/getAll', method:'get' }).then(res=>{ console.log(res.data.data) })
1.1.2. 使用 GET 方式请求,参数值直接放在路径中
接口
@GetMapping("/get/{id}") public ResResult getUserById(@PathVariable("id") Long id){ User user = userService.getById(id); return ResResult.okResult(user); }
请求
axios({ url:'http://localhost:8080/get/1', method:'get' }).then(res=>{ console.log(res.data.data) })
1.1.3. 使用 GET 方式请求,参数拼接在路径中
拼接方式 ①
使用 ? 进行参数拼接
接口
@GetMapping("/get") public ResResult getUserByIds(@RequestParam("id") Long id){ User user = userService.getById(id); return ResResult.okResult(user); }
请求
axios({ url:'http://localhost:8080/get?id=1', method:'get' }).then(res=>{ console.log(res.data.data) })
拼接方式 ②
使用 params 【单个参数】
接口
@GetMapping("/get") public ResResult getUserByIds(@RequestParam("id") Long id){ User user = userService.getById(id); return ResResult.okResult(user); }
请求
axios({ url:'http://localhost:8080/get', params:{ id:'2' }, method:'get' }).then(res=>{ console.log(res.data.data) })
拼接方式 ③
使用 params 【多个参数】
接口
@GetMapping("/get") public ResResult getUserByIds(@RequestParam("id") Long id,@RequestParam("username") String username){ LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); wrapper.eq(User::getUsername,username); wrapper.eq(User::getId,id); User user = userService.getOne(wrapper); return ResResult.okResult(user); }
请求
axios({ url:'http://localhost:8080/get', params:{ id:'2', username:'swx' }, method:'get' }).then(res=>{ console.log(res.data.data) })
当 POST 有参请求且是简写时,要以 JSON 格式请求
axios.post('http://localhost:8080/post',"id=2&username=swx").then(res=>{ console.log(res.data.data) }).catch(err=>{ console.log('timeout') console.log(err) })
1.1.4. GET 请求的简写方式
无参时:
axios.get('http://localhost:8080/get/getAll').then(res=>{ console.log(res.data.data) }).catch(err=>{ console.log('timeout') console.log(err) })
有参时:
axios.get('http://localhost:8080/get',{params:{id:'2',username:'swx'}}).then(res=>{ console.log(res.data.data) }).catch(err=>{ console.log('timeout') console.log(err) })
1.2. POST 请求
注意:POST 请求的有参、无参请求与如上的 GET 是一样的,只不过是请求方式名换一下。
如下是 POST 请求简写与传入配置项写法时,关于请求体格式的一点区别:
接口
var express = require('express') var path = require('path') var bodyParser = require('body-parser') const { json } = require('body-parser') var app = express() app.use(express.static(path.join(__dirname, 'public'))) app.use(bodyParser.urlencoded({ extended: false })) app.use(bodyParser.json()) app.get('/a', function(req, res) { console.log(req.query) res.send({ "id": 1, "name": "张三" }) }) app.listen(3000, function() { console.log('app is runing...') })
请求
写法 ①
如果使用 Axios 的 POST 请求的简写形式,需要将数据以 JSON 格式传递。
axios.post('/a', { "id": 5, "name": "ssss" }).then(response => { console.log('/a1', response.data) }, error => { console.log('错误', error.message) })
请求
写法 ②
如果将数据直接作为请求体传递,不需要将数据写成 JSON 格式。axios 会根据请求头的 Content-Type 自动处理数据格式。
axios({ method: 'POST', url: '/a', data: { id: 1, name: "张三" } }) .then(response => { console.log('/a', response.data) return response.data }, error => { console.log('错误', error.message) })
二、请求失败处理
axios.get('http://localhost:8080/get',{params:{id:'2',username:'swx'}}).then(res=>{ console.log(res.data.data) }).catch(err=>{ console.log('timeout') console.log(err) })
三、axios 并发请求
方式 1
接口
@GetMapping("/get/getAll") public ResResult getAllUser(){ List list = userService.list(); return ResResult.okResult(list); } @GetMapping("/get/get") public ResResult getUserByIdt(@RequestParam("id") Long id){ User user = userService.getById(id); return ResResult.okResult(user); }
请求
axios.all([ axios.get('http://localhost:8080/get/getAll'), axios.get('http://localhost:8080/get/get',{params:{id:'1'}}) ]).then(res=>{ //返回的是数组,请求成功返回的数组 console.log(res[0].data.data), console.log(res[1].data.data) }).catch(err=>{ console.log(err) })
方式 2:使用 spread 方法处理返回的数组
axios .all([ axios.get("http://localhost:8080/get/getAll"), axios.get("http://localhost:8080/get/get", { params: { id: "1" } }), ]) .then( axios.spread((res1, res2) => { console.log(res1.data.data), console.log(res2.data.data); }) ) .catch((err) => { console.log(err); });
四、axios 全局配置
axios.defaults.baseURL='http://localhost:8080'; //全局配置属性 axios.defaults.timeout=5000; //设置超时时间 //发送请求 axios.get('get/getAll').then(res=>{ console.log(res.data.data) }); axios.post('post/getAll').then(res=>{ console.log(res.data.data) });
五、axios 实例
//创建实例 let request = axios.create({ baseURL:'http://localhost:8080', timeout:5000 }); //使用实例 request({ url:'get/getAll' }).then(res=>{ console.log(res.data.data) }); request({ url:'post/getAll', method:'post' }).then(res=>{ console.log(res.data.data) })
六、axios 拦截器
axios 提供了两大类拦截器:
- 一种是请求方向的拦截(成功的、失败的)
- 一种是响应方向的拦截(成功的,失败的)
拦截器作用:
比如:请求之前在请求头加 token、强制登录
响应的时候可以进行相应的数据处理
请求拦截器
//创建实例 let request = axios.create({ baseURL:'http://localhost:8080', timeout:5000 }); //配置axios拦截器 request.interceptors.request.use(config=>{ console.log("请求进来了...") console.log("请求成功方向") console.log(config.data.data) //放行请求,这一步很重要,否则报错 return config; },err=>{ console.log("请求进来了...") console.log("请求失败方向") console.log(err) }); //如果没有创建实例,则使用以下方式 //配置axios拦截器 // axios.interceptors.request.use(config=>{ // console.log("请求进来了...") // console.log("请求成功方向") // console.log(config) // //放行请求 // return config; // },err=>{ // console.log("请求进来了...") // console.log("请求失败方向") // console.log(err) // }); //使用实例 request({ url:'get/getAll' }).then(res=>{ console.log(res.data.data) });
响应拦截器
//创建实例 let request = axios.create({ baseURL:'http://localhost:8080', timeout:5000 }); //配置axios拦截器 request.interceptors.response.use(config=>{ console.log("响应进来了...") console.log("响应成功方向") console.log(config.data.data) //放行响应 return config; },err=>{ console.log("响应进来了...") console.log("响应失败方向") console.log(err) }); //使用实例 request({ url:'get/getAll' }).then(res=>{ console.log(res.data.data) });
七、vue 中封装 axios
封装在 request.js 中
//导入axios import axios from 'axios' //创建axios实例 const service = axios.create({ baseURL: 接口地址, timeout: 5000 }) //请求拦截器 service.interceptors.request.use( config => { if (store.getters.token) { config.headers['token'] = getToken() } //放行请求 return config }, error => { console.log(error) return Promise.reject(error) } ) //响应拦截器 service.interceptors.response.use( response => { //返回的数据 const res = response.data if (res.code !== 200) { Message({ message: res.message || 'Error', type: 'error', duration: 5 * 1000 }) // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; if (res.code === 50008 || res.code === 50012 || res.code === 50014) { // to re-login MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { confirmButtonText: 'Re-Login', cancelButtonText: 'Cancel', type: 'warning' }).then(() => { store.dispatch('user/resetToken').then(() => { location.reload() }) }) } return Promise.reject(new Error(res.message || 'Error')) } else { return res } }, error => { console.log('err' + error) // for debug Message({ message: error.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } ) export default service
哪个模块需要发送请求直接引入即可,将以上实例导入
比如:此模块的所有请求接口:api 下的 skuInfo.js
//导入axios实例 const api_name = '/admin/product/skuInfo' export default { getPageList(page, limit, searchObj) { return request({ url: `${api_name}/${page}/${limit}`, method: 'get', params: searchObj }) }, save(role) { return request({ url: `${api_name}/save`, method: 'post', data: role }) }, //新人专享 isNewPerson(id, status) { return request({ url: `${api_name}/isNewPerson/${id}/${status}`, method: 'get' }) }, }
list.vue 页面中使用
//先导入 import api from '@/api/product/skuInfo' api.getPageList(this.page, this.limit, this.searchObj).then( response => { debugger this.list = response.data.records this.total = response.data.total // 数据加载并绑定成功 this.listLoading = false } ) } api.save(this.skuInfo).then(response => { if (response.code) { this.$message({ type: 'success', message: response.message }) this.$router.push({ path: '/product/skuInfo/list' }) this.saveBtnDisabled = false } }) //新人专享 handleNewPersonChange(index, row) { api.isNewPerson(row.id, row.isNewPerson).then(response => { this.$message({ type: 'info', message: '操作成功' }) this.fetchData() }) } }
main.js 中引入使用
import * as API from '@/api' Vue.prototype.$API = API