引言
本文将融百家之言,成xhr家族之唱,依次介绍xhr嫡次子axios(最得前端厚爱),ajax为xhr家族嫡长子(资历最长),老三fetch(网络请求新秀)为义子(原理不是基于xhr的,基于promise),携带cookie发起请求实例以及面试题带记。
一、ajax/axios/fetch简介:
1.ajax简介
姓名:ajax
职业:基于 promise 的网络请求(可以直接使用)
工作地点:浏览器和 node.js
生产工艺:核心原生XHR,外挂Promise,符合最新的ES规范
2.axios简介
姓名:axios
职业:基于 promise 的网络请求库 (使用时需要下载安装)
工作地点:浏览器和 node.js
生产工艺:核心原生XHR,外挂Promise,符合最新的ES规范
技能特长:
(1)在浏览器创建 XMLHttpRequests,在 node.js 创建 http 请求;
(2)支持 Promise API拦截请求和响应转换请求和响应数据,取消请求自动转换JSON数据客户端支持防御XSRF;
(3)可以发起jsonp请求,默认不携带cookie
3.fetch简介
姓名:fetch
职业:基于 promise 的网络请求
工作地点:浏览器
生产工艺:核心基于Promise,非xhr
技能特长:
(1)只对网络请求报错,对于错误状态码400/500都会当作成功的请求,只有网络出问题才会reject;
(2)可以配合async/await一起请求,避免ajax/axios请求不成功,影响后面代码执行;
(3)默认不会带cookie,需要添加配置项: fetch(url, {credentials: ‘include’});
(4)fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费;
(5)fetch没有办法原生监测请求的进度,而XHR可以;
(6)fetch的第12个.then拿到接口返回的数据
参考文章:fetch与axios、浏览器内多个标签页面通信及安全问题
二、axios案例分享
1.axios请求携带cookie示例
axios的请求配置默认是不携带 cookie 信息的,如何使得ajax请求携带cookie呢?
对于前端而言,只需要将axios的对象属性 withCredentials属性设为 true,
注意,axios的headers属性设为空对象,不然接口会报cors的错误哦
后端同学请注意,前端开启axios的 withCredentials属性后,
(1)服务端的headers属性中的Access-Control-Allow-Origin将不能设为’*';
(2)服务端的headers属性中的Access-Control-Allow-Credentials需设为true
注意,这种前端、后端配合的axios携带cookie的请求方式可以解决——跨域问题哦!
开启withCredentials属性,携带cookie代码示例
1.1局部封装:axios开启withCredentials属性
import axios from 'axios';
import qs from 'qs'
// 对post请求二次封装
function cookiePost(url, params) {
return new Promise((resolve, reject) => {
let query = {
...params,
}
axios({
url: url,
headers: {},
method: "get",
data: qs.stringify(query),
withCredentials: true,
timeout: 30000
})
.then((res) => {
let data = res.data;
resolve(data);
})
.catch((err) => {
reject(err.data);
});;
});
}
function ckGet(url, params) {
return new Promise((resolve, reject) => {
axios({
url,
params,
headers: {
// "Access-Control-Allow-Origin": "*",
},
method: "get",
withCredentials: true
})
.then((res) => {
let data = res.data;
resolve(data);
})
.catch((err) => {
reject(err.data);
});
})
}
function cookieGet(url, params) {
return new Promise((resolve, reject) => {
let query = {
...params
}
url += qs.stringify(query)
axios
.get(url, { withCredentials: true })
.then((res) => {
let data = res.data;
resolve(data);
})
.catch((err) => {
reject(err.data);
});
})
}
//可以将封装好的axios挂载在window上对外暴露
window.Axios = {
cookiePost,
cookieGet,
ckGet
};
项目中使用封装好的cookiePost示例
export function post(params) {
const url = ``;
return Axios.cookiePost(url, {...params});
}
1.2全局封装:axios开启withCredentials属性
import axios from 'axios';
axios.defaults.withCredentials=true;
参考文章:axios携带cookie
1.3 fetch携带cookie方法
同axios,fetch默认不携带cookie,
fetch(url, {
method: 'POST',
credentials: "include"
}).then((response)=>response.json())
.then((responseJsonData)=> {
//fetch的第二个.then才能拿到数据对象
callback && callback(responseJsonData);
}).catch((error)=> {
errorCallBack && errorCallBack(error);
console.log(error);
});
参考文章: 同源、跨域(以及ajax、fetch携带cookie)
1.4 ajax携带cookie并进行跨域请求方法
let url = ``;
const params={}
let res = await $.ajax({
url,
type: "POST",
dataType: "json",
data: params,
xhrFields: {
withCredentials: true, // 此字段标识要跨域传数据
},
crossDomain: true,
});
console.log(res)
2.axios请求拦截器响应拦截器加密封装
// 请求拦截器
axios.interceptors.request.use(
(config) => {
return config;
},
(error) => {
return Promise.error(error);
}
);
// 响应拦截器
axios.interceptors.response.use(
(response) => {
if (response.status === 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
},
// 服务器状态码不是200的情况
(error) => {
}
);
参考文章:1.http://zhenglinglu.cn/pages/6ec693/#_1%E3%80%81%E5%85%A8%E5%B1%80%E8%AE%BE%E7%BD%AE
2.https://blog.csdn.net/xiashiqi_blog/article/details/84979134
3.https://blog.csdn.net/lfcss/article/details/121275023
4.https://blog.csdn.net/lfcss/article/details/121275023