关于axios
官方文档给出的特征说明是:
- 从浏览器中创建
XMLHttpRequest
- 从 node.js 发出 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防止CSRF/XSRF
但是它的使用和我们之前常用的jquery ajax
和fetch
的还是有一定区别的,具体如下:
-
jquery ajax
提交数据的时候,默认是以FormData的形式提交的,也就是Content-Type:"application/x-www-form-urlencoded"
axios
默认使用的是Payload形式提交数据,也就是Content-Type:"application/json"
-
axios
防止CSRF/XSRF的原理是:设置xsrfCookieName: 'XSRF-TOKEN'
是用作 xsrf token 的值的cookie的名称。
axios
会让你的每个请求都带一个从cookie
中拿到的key
,根据浏览器的同源策略,假冒的网站是拿不到cookie
中的key
的,后台可以因此辨别这个请求是否在用户假冒网站上的舞蹈输入,从而采取正确的策略。 -
axios
不支持JSONP
,但是可以自己封装:
//axios本版本不支持jsonp 自己拓展一个
axios.jsonp = (url) => {
if (!url) {
console.error('Axios.JSONP 至少需要一个url参数!')
return;
}
return new Promise((resolve, reject) => {
window.jsonCallBack = (result) => {
resolve(result)
}
var JSONP = document.createElement("script");
JSONP.type = "text/javascript";
JSONP.src = `${url}&callback=jsonCallBack`;
document.getElementsByTagName("head")[0].appendChild(JSONP);
setTimeout(() => {
document.getElementsByTagName("head")[0].removeChild(JSONP)
}, 500)
})
}
-
axios
支持并发请求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));
使用实例:
- get请求
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 可选地,上面的请求可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
- post请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
在这之前,我对axios的种种并不十分care,因为我当前的项目的复杂程度并十分复杂,并不能体会到axios封装后带来的好处,知道我遇到了如下问题:
- fetch确实在返回的错误处理上让人忍不住吐槽,及时返回的http码不是200依然执行成功回调
- axios确实相较于fetch更容易上手,这是我作为一个前端小白的直观感受
- 在通过Redux进行异步请求时我们通常将action,actionType,reducer以及其他逻辑代码分开放置,但是当我们需要利用上一次异步请求的返回结果去做其他的事情的时候,我的第一直觉是可以使用async/await来解决这个问题,但是实际操作中我们通常遇到的情况如下:
demo.js
import { handleClick } from './action';
class Demo extends PureComponent{
...
handleClick(){
// 这里只能调用异步请求,等异步请求成功后将请求的数据放到store中
// 再通过mapStateToProps函数将Store中的状态映射到组件上
// 在CompententWillReceiveProps等生命周期中调用handleClickData
this.props.handleClick();
}
render(){
return(
)
}
}
...
const mapDispatchToProps = (dispatch) => {
return{
handleClick: (item) => dispatch(handleClick),
handleClickData: (item) => dispatch(handleClickData)
}
}
action.js
...
export const handleClick = () => {
return (dispatch) => {
fetch(url, {
method: 'GET'
}).then((res) => {
if(res.ok) {
return res.json()
} else {
return res
}
}).then((data) => {
if(data.status) {
reject(data)
} else {
dispatch({
type:HANDLECLICK,
data
})
}
}).catch((e) => {
reject(e)
})
}
}
但是当我们采用了axios时可以利用其帮我们封装好的Priomise来精简我们的代码
demo.js
handleClick(){
handleClick().then(() => {
// handleClickData
}).catch((e) => {
// handleError
})
}
action.js
export const getSecondModal = (param) => {
return (dispatch) => {
const promise = new Promise(async (resolve, reject) => {
let res = null;
try {
res = await axios.get(url);
} catch (e) {
reject(e);
return
}
dispatch({
type:HANDLECLICK,
data
})
resolve(res.data)
})
return promise
}
}