xhr
创建xhr实例,发送ajax请求
AJAX核心:基于XMLHttpRequest创建HTTP请求
let xhr = new XMLHttpRequest;
xhr.open('GET', './1.json');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.status !== 200) return;
if (xhr.readyState === 2) {
console.log(xhr.getAllResponseHeaders());
}
if (xhr.readyState === 4) {
console.log(xhr.response);
}
};
xhr.send(Qs.stringify({
name: 'xxx',
lx: 0
}));
- 需要⚠️注意的地方
- 设置请求头信息&超时时间&携带资源凭证 需要在open之后send之前,否则会报错
- 请求头信息中不允许出现中文
xhr.setRequestHeader('name', '肯德基'); 请求头信息中不允许出现中文
AJAX方法&属性
xhr.readyState ajax状态
监听请求的过程,在不同的阶段做不同的处理「包含获取服务器的响应信息」
- 0 UNSENT
- 1 OPENED
- 2 HEADERS_RECEIVED 响应头信息已经返回
- 3 LOADING 响应主体信息正在处理
- 4 DONE 响应主体信息已经返回
xhr.status HTTP状态码
- 200 OK
- 202 Accepted :服务器已接受请求,但尚未处理(异步)
- 204 No Content:服务器成功处理了请求,但不需要返回任何实体内容
- 206 Partial Content:服务器已经成功处理了部分 GET 请求(断点续传 Range/If-Range/Content- Range/Content-Type:”multipart/byteranges”/Content-Length….)
不建议用这个方法做断点续传 - 301 Moved Permanently 永久转移 「域名迁移」
- 302 Move Temporarily 临时转移 「负载均衡」
处理大量请求时,一台服务器满了,转去另外一台服务器 - 304 Not Modified
- 305 Use Proxy
- 400 Bad Request : 请求参数有误
- 401 Unauthorized:权限(Authorization)
- 403 Forbidden 服务器拒绝执行「为啥可能会已响应主体返回」
- 404 Not Found 地址错误
- 405 Method Not Allowed 请求方式不被允许
- 408 Request Timeout 请求超时
- 500 Internal Server Error 未知服务器错误
- 503 Service Unavailable 超负荷
- 505 HTTP Version Not Supported
xhr.response/responseText/responseXML 获取响应主体信息
服务器返回的响应主体信息的格式
- 字符串「一般是JSON字符串」 「最常用」
- XML格式数据
- 文件流格式数据「buffer/二进制...」
- ...
xhr.getResponseHeader/getAllResponseHeaders
获取响应头信息 xhr.getResponseHeader/getAllResponseHeaders
xhr.send 请求主体(body)传递给服务器的数据格式:
发送请求「send中传递的信息,就是设置的请求主体(body)信息」
请求主体(body)传递给服务器的数据格式:
1.form-data 主要应用于文件的上传或者表单数据提交
let fd = new FormData;
fd.append('lx', 0);
fd.append('name', 'xxx');
xhr.send(fd);
header: xhr.setRequestHeader('Content-Type', 'multipart/form-data')
2.x-www-form-urlencoded 要求一种格式的字符串
格式:“lx=1&name=xxx” 「常用」
Qs库: $npm i qs
Qs.stringify/parse:实现对象和urlencoded格式字符串之间的转换
header: xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(Qs.stringify({
lx: 0,
name: 'xxx'
}));
3.raw字符串格式
普通字符串 -> text/plain JSON字符串 -> application/json => JSON.stringify/parse 「常用」 XML格式字符串 -> application/xml
4.binary进制数据文件「buffer/二进制...」
一般也应用于文件上传
图片 -> image/jpeg
EXCEL -> application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
get & post的区别。
- method 请求方式:GET(get/delete/head/options...) / POST(post/put/patch...)
GET请求传递给服务器的信息,除了请求头传递以外,要求基于URL问号传参传递给服务器
xhr.open('GET', './1.json?lx=1&name=xxx')
POST请求要求传递给服务器的信息,是基于请求主体(body)传递
xhr.send('lx=1&name=xxx')
-
GET传递的信息不如POST多,因为URL有长度限制「IE->2KB」,超过这个长度的信息会被自动截掉,这样导致传递内容过多,最后服务器收到的信息是不完整的!!POST理论上是没有限制的,但是传递的东西越多,速度越慢,可能导致浏览器报传输超时的错误,所以实际上我们会自己手动做限制!!
-
GET会产生缓存「浏览器默认产生的,不可控的缓存」:两次及以上,请求相同的API接口,并且传递的参数也一样,浏览器可能会把第一次请求的信息直接返回,而不是从服务器获取最新的信息!!
在请求URL的末尾设置随机数,以此来清除GET缓存的副作用
xhr.open('GET', './1.json?lx=1&name=xxx&_'+Math.random()) -
POST相对于GET来讲更安全一些:GET传递的信息是基于URL末尾拼接,这个随便做一些劫持或者修改,都可以直接改了,而POST请求主体信息的劫持,没那么好做!!但是“互联网面前,人人都在裸奔”!!所以不管什么方式,只要涉及安全的信息,都需要手动加密「因为默认所有的信息传输都是明文的」!!
axios二次配置
/*
* 提取axios的公共配置信息,进行二次配置
*/
/* import axios from 'axios';
import Qs from 'qs'; */
// 大部分请求基于这个前缀
// =>小部分在发送请求的时候单独的在配置baseURL
axiox.get('list',{
baseURL:'http://www.kendeji.com'
})
// =>也可以基于axios.create()创建不同的实例,给每一个实例单独管理公共信息
//const axios1= axios.create()
//axios1.defaults.baseURL = '...'
//const axios2= axios.create()
//axios2.defaults.baseURL = '...'
//axios1.post()
// =>地址不一样可能是根据当前环境(生产/开发/测试)
/* const env = process.env.NODE_ENV;
switch (env) {
case "dev":
axios.defaults.baseURL = "http://127.0.0.1:8081/api";
break;
case 'test':
axios.defaults.baseURL = "http://192.168.1.20:8081/api";
break;
case 'pro':
axios.defaults.baseURL = "http://www.zhufengpeixun.cn/api";
break;
} */
axios.defaults.baseURL = "http://www.zhufengpeixun.cn/api";
/*
* 传递给服务器的数据格式
* FormData multipart/form-data
* x-www-form-urlencoded application/x-www-form-urlencoded
* raw(例如:json文本 text文本) application/json
* binary application/octet-stream
*/
// axios.defaults.headers.post['Content-Type']
axios.defaults.headers['Content-Type'] = "application/x-www-form-urlencoded";
axios.defaults.transformRequest = data => Qs.stringify(data);
/*
* 其它的常规配置项
*/
// axios.defaults.timeout = 10000;
// axios.defaults.withCredentials = true;
axios.defaults.validateStatus = status => {
return /^(2|3)\d{2}$/.test(status);
};
/*
* 请求拦截器:在客户端把信息发送给服务器之前,我们拦截一下,对一些公共的信息做配置
* config存储的是所有配置项信息
* 真实项目中,我们往往需要校验是否登录或者接口的合法性
* 登录成功后,服务器首先基于JWT生成一个TOKEN信息,并且基于响应头/响应主体信息返回给客户端;客户端会把TOKEN信息存储到本地(localStorage);再下一次发送请求的时候,客户端会基于请求头,把TOKEN传递给服务器,服务器获取TOKEN信息后,先校验是否合法(合法:接口请求合法或者当前用户是登录的);
*/
axios.interceptors.request.use(config => {
let token = localStorage.getItem('token');
token && (config.headers['Authorization'] = token);
return config;
});
/*
* 响应拦截器:当服务器端把数据返回给客户端,在客户端自己.then之前,做一些处理
* axios.get('/userlist')[拦截器做的事情].then();
* 实例【.then(A,B)】.then(...)
*/
axios.interceptors.response.use(response => {
// 请求成功(只把响应主体信息返回)
// 还可能对返回结果中公共的部分做一些处理
return response.data;
}, reason => {
// 请求失败:
// 1.向服务器发送请求,服务器有反馈,只不过反馈信息是以4/5开头的
// 2.向服务器发送请求,服务器没有任何的反馈(断网)
let response = reason.response;
if (response) {
// 根据不同的状态码做不同的提示处理
switch (response.status) {
case 401: //=>权限(例如:未登录)
break;
case 403: //=>服务器拒绝执行(例如:token过期)
break;
case 404: //=>找不到页面
break;
case 500: //=>服务异常
break;
case 503: //=>服务器超负载
break;
}
return Promise.reject(reason);
return;
}
// 是否断网
if (!window.navigator.onLine) {
// ...
}
return Promise.reject(reason);
});
/* export default axios; */