axios
的特点
1. 支持浏览器和node.js
2. 支持promise
3. 能拦截请求和响应
4. 能转换请求和响应数据
5. 能取消请求
6. 自动转换JSON数据
7. 浏览器端支持防止CSRF(跨站请求伪造)
axios
提问
- 如何将
axios
异步请求同步化处理?
//使用 asyns/await
async getHistoryData (data) {
try {
let res = await axios.get('/api/survey/list/', {
params: data
})
this.tableData = res.data.result
this.totalData = res.data.count
} catch (err) {
console.log(err)
alert('请求出错!')
}
}
-
为何官方推荐使用
axios
而不用vue-resource
?在
Vue1.x
中,官方推荐使用的ajax
库是vue-resource。到了Vue2.x
,官方(尤大)推荐的ajax
库改为了Axios
,按照说法是因为已有一个更完备的轮子,就不需要造一个新的。 -
你了解
axios
的原理吗?有看过它的源码吗? - 你有封装过
axios
吗?主要是封装哪方面的?
- 封装request.js, 导出service。
import axios from 'axios'
import {getToken} from '@/utils/auth'const service = axios.create({
baseURL: process.env.BASE_API, // url = base url + request url
timeout: 5000
})
// request拦截器
service.interceptors.request.use(
config => {
// do something before request is sent
config.headers['x-access-token'] = getToken()
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
// response拦截器
service.interceptors.response.use(
response => {
/**
* 1.code为非000000是抛错 可结合自己业务进行修改
* 2.response 是 http 封装的实体类,response.data 使我们真正的响应数据
*/
// const res = response.data
// console.log("拦截前的response:",response);
return response.data
},
error => {
console.log('err' + error) // for debug
return Promise.reject(error)
}
)
export default service - 创建http.js。 导出http
/**
* Created by czx on 2020/1/17.
*/
import request from './request'
import qs from 'qs'
// qs.parse()将URL解析成对象的形式;qs.stringify()将对象 序列化成URL的形式,以&进行拼接const Http = {}
Http.request = request/**
* @desc Http表单方式提交
* @param url 请求的url 参数 /loginAsync.do
* @parrm method 请求方法类型 类似post get
* @param params {} 参数对象 data: {username: username, password: password},
*/
Http.commitForm = function (url, params, config = {}) {
const _config = {
url,
method: 'post',
data:params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: params => qs.stringify(params, { arrayFormat: 'repeat' })// 修改数组传递格式
}
config = Object.assign(config, _config)
return request(config)
}/*
* JSON格式的接口,默认为post请求
* 传入 config={method: 'get'}则变为get请求
*/
Http.Json = function(url, params, config = {}) {
const _config = {
method: 'post',
url: url,
data: params,
headers: {
'Content-Type': 'application/json'
}
}
config = Object.assign(_config, config)
return request(config)
}Http.JsonPic = function(url, params) {
return request.post(url, params)
}Http.post = function(url, params, config = {}) {
const _config = {
method: 'post',
url: url,
data: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: function(params) {
return qs.stringify(params, { arrayFormat: 'repeat' }) // 修改数组传递格式
}
}
config = Object.assign(_config, config)
return request(config)
}Http.get = function(url, params, config = {}) {
const _config = {
method: 'get',
url: url,
params: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
paramsSerializer: function(params) {
return qs.stringify(params, { arrayFormat: 'repeat' }) // 修改数组传递格式
}
}
config = Object.assign(_config, config)
return request(config)
}/*Http.mapUrl = function(url, params) {
if (typeof params === 'object') {
params = encodeUrlParam(params)
} else {
params = null
}
if (params) {
if (url.indexOf('?') >= 0) {
url += '&' + params
} else {
url += '?' + params
}
}
if (!process.env.BASE_API || process.env.BASE_API === '/' || process.env.BASE_API === '') {
return window.location.origin + url
}
return process.env.BASE_API + url
}*/export default Http
- 其中request.js中用到的 {getToken} 方法,在auth.js 中封装
import Cookies from 'js-cookie'
const TokenKey = 'x-access-token'export function getToken() {
return Cookies.get(TokenKey)
}export function setToken(token) {
return Cookies.set(TokenKey,token)
}export function removeToken() {
return Cookies.remove(TokenKey)
} - 在业务api使用
import Http from '@/utils/http.js' export function login(param) { return Http.post('/login',param) } export function register(param) { return Http.post('/register',param) }
- 在vue页面中引用
import {login, register} from '@/api/login'
5. 如何中断(取消)axios
的请求?
- 在项目中碰到了短时间多次请求的情况,为了更好地用户体验和性能,需要取消上次axios请求
- 前端发起请求后,后端还未全部返回请求数据时,终止请求,不再返回数据。
- 栗子: 【附件上传】:前端上传一个1G大小的压缩文件时,耗时大概一两分钟,在上传到50%的时候,用户要取消上传,此时,就要执行如题所探讨的终止请求动作。
- 解决方案:利用axios请求的config参数,向axios添加一个包含cancelToken的config配置对象。
export default { data() { return {cancelTokenFn: null} }, methods: { cancelTokenDone() { const _this = this const CancelToken = axios.CancelToken; this.cancelTokenFn && this.cancelTokenFn(); this.cancelTokenFn = null; axios.get('url', { cancelToken: new CancelToken(function executor(c) { _this.cancelTokenFn = c }) }) .then(function (response) { const data = response.data; console.log(data); }) .catch(function (error) { console.log(error) }) } } }
this.cancelTokenFn()
-
axios
怎么解决跨域的问题?-
如果
server
端是自己开发的,那么修改相关代码支持跨域即可。如果不是自己开发的,那么可以自己写个后端转发该请求,用代理的方式实现。 -
跨域这个行为是浏览器禁止(浏览器不允许当前页面的所在的源去请求另一个源的数据)的,但是服务端并不禁止
-
源指协议、端口、域名。只要这个3个中有一个不同就是跨域。 这里列举一个经典的列子:
协议跨域: http://a.baidu.com访问https://a.baidu.com; 端口跨域: http://a.baidu.com:8080访问http://a.baidu.com:80; 域名跨域: http://a.baidu.com访问http://b.baidu.com;
-
关键字:
Access-control-Allow-origin
、跨域 -
A) 开发模式下,可以在
config
中配置proxyTable
即可 -
B) 服务端基于spring实现
-
C)
CORS
:①即跨源资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。 ②它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。③但是CORS
也具有一定的风险性,比如请求中只能说明来自于一个特定的域但不能验证是否可信,而且也容易被第三方入侵。 ④这里一般需要后端配合,开启cors
。一般各种语言都有类似的包。比如NodeJS的koa2-cors
-
D)
Nginx
代理proxy
-
E)
express
代理 -
请求头自动携带
cookie
时:config
中配置withCredentials:true
,否则为false
【看到有人说:withCredentials
为true
的情况下,后端要设置Access-Control-Allow-Origin
为你的源地址,例如http://localhost:8080
,不能是*
,而且还要设置header('Access-Control-Allow-Credentials: true')
】 -
config
中配置qs
:避开ajax
信使请求,并兼容Android
?
import Qs from 'qs'
-