ajax:依赖XMLHttpRequest,再基于ajax的四步,实现从服务器获取数据
- 请求方式:GET(GET/DELETE/HEAD/OPTIONS) POST(POST/PUT/PATCH)
- - GET和POST的区别:
- 约定俗成的区别:GET请求传递给服务器的信息基于URL问号传参;POST是基于请求主体;
- GET传输内容有大小限制(ie2kb,google4kb)[URL长度有限制];
- POST相对于GET来讲更安全【相对安全】;
- GET会产生不可控的缓存,两次请求的地址和参数相同时,会把上一次请求的值传回来【保证每次请求的地址和参数不一样(URL末尾加随机数/时间戳)】。
- - xhr.readyState
- 0 请求未初始化 创造出来xhr实例就是0
- 1 服务器连接已建立 执行open方法后就会由0变成1
- 2 请求已接收 响应头信息已经返回
- 3 请求处理中 响应主体信息正在处理
- 4 请求已完成,且响应已就绪 响应主体信息已经返回
- - xhr.status HTTP状态码
- 1xx:信息响应类,表示接收到请求并且继续处理
- 2xx:处理成功响应类,表示动作被成功接收、理解和接受
- 3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
- 4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
- 5xx:服务端错误,服务器不能正确执行一个正确的请求
- 200:OK
- 301 302(307) 304
- 400(服务器拒绝响应并告诉原因) 401 403(拒绝执行) 405(请求方式出错) 408(请求超时)
- 500(服务器错误) 501 502(网关错误) 503(服务器超负荷)
- - xhr.send(): 基于请求主体把信息主体传给服务器 传输的数据有格式要求:一般格式对象不支持,你写的对象,浏览器都会变成字符串传递给服务器;我们需要设置请求头中的 Content-Type 让其和传递的格式相符
- 字符串格式
- JSON格式字符串: 'Content-Type', application/json
- URLENCODED格式字符串 'Content-Type', 'application/x-www-form-urlencoded'
- 普通文本:'Content-Type',text/plain
- FormDate格式对象:【文件上传】
- 'Content-Type', 'multipart/form-data';boundary=...
- buffer格式【进制编码格式】
- - xhr常用的属性
- onabort
- ontimeout
- readyState
- response/responseText
- status
- timeout
- withCredentials:false 跨域请求是否允许携带资源凭证(例如:cookie)
- upload.onprogress 监听文件上传的进度
- - xhr常用的方法
- abort
- getAllResponseHeaders
- getResponseHeader
- open
- overrideMimeType
- send
- setRequestHeader
$ajax:是JQ类库对原生ajax的封装,基于回调函数方式封装
核心还是XMLHttpRequest
当请求成功,触发success回调函数执行,在这个函数中可以拿到从服务器获取数据
弊端:串行,容易产生回调地狱
axios:基于promise封装的ajax库
核心还是XMLHttpRequest
优势:基于promise,更好的管理异步编程
每一次基于axios发送请求,都会返回promise实例,请求成功,实例fulfilled,值是从服务器获取的结果;请求失败,实例是rejected,值是失败的原因。
axios.request({
url:'',
method:'',
params:{}
})
axios.get({
params:{}
})
基于axios发送请求
- axios([config])
- axios.request([config])
- axios.get/delete/head([url],[config])
- axios.post/put([url],[data],[config])
- [config]配置项:www.axios-js.com/zh-cn/docs/
- url:'';
- baseURL:请求地址的公共前缀。最后向服务器发送请求,请求地址baseURL+url。如果url中存在http(s)://则不拼接baseURL。
- method:'get';
- params:对象 URL问号传参信息,我们传递的是一个对象,axios内部会把对象变为urlencoded格式字符串,拼接到url末尾。
- data:字符串/FormData对象/对象 POST 系列请求,基于请求主体传递给服务器的信息,格式要求,对于原生ajax来讲,不能传递普通对象,但是axios内部做了封装,会把普通对象默认变为JSON格式字符串。【而且axios内部会根据我们编写的格式自动设置的请求头Content-Type的类型值。】
- headers:对象 自定义请求头信息
- timeout:设置超时时间
- withCredentials:跨域是否携带cookie
- responseType:'json/arraybuffer/blob/text/document',预设服务器响应主体返回的信息格式(预设:服务器返回啥格式是服务器决定的,axios只是会把服务器返回的结果变为我们指定的格式)
- onDownloadProgress onDownloadProgress:函数
- validateStatus:status=>status >= 200 && status < 300 设置服务器返回什么样的HTTP状态码算作请求成功,默认以2开始的才算
- transformRequest:函数 只对post系列请求有作用,基于请求主体传递给服务器的data,在发送前做格式化处理。
axios二次封装:把每一次发送请求公共的配置项统一封装好,以后再发请求,公共的部分就不用再写了,简化axios的使用。
axios.get('/user/list')
.then(value => {
console.log(value);
});
axios.get('/user/list').then(response => {
// 请求成功:response
// + status/statusText
// + request 原生的XHR对象
// + config 用户设置的配置项
// + headers 响应头信息
// + data 响应主体信息
console.log(response.data);
}).catch(reason => {
// 请求失败:做提示(根据不同的情况做不同的提示处理)
// @1 HTTP状态码不对 @2 请求超时/中断 @3 断网
alert('小主,当前网络繁忙,请稍后再试~');
});
响应拦截器
请求拦截器
http.js 公共文件
// 检测是否为纯粹的对象
const isPlainObject = function isPlainObject(obj) {
let proto, Ctor;
if (!obj || Object.prototype.toString.call(obj) !== "[object Object]") return false;
proto = Object.getPrototypeOf(obj);
if (!proto) return true;
Ctor = proto.hasOwnProperty('constructor') && proto.constructor;
return typeof Ctor === "function" && Ctor === Object;
};
/* 对AXIOS的二次封账「发送请求公共部分的提取」 */
axios.defaults.baseURL = 'http://127.0.0.1:9999';
axios.defaults.withCredentials = true;
axios.defaults.timeout = 60000;
axios.defaults.transformRequest = data => {
if (isPlainObject(data)) data = Qs.stringify(data);
return data;
};
axios.defaults.validateStatus = status => {
return status >= 200 && status < 400;
};
// 请求拦截器
axios.interceptors.request.use(config => {
return config;
});
// 响应拦截器
axios.interceptors.response.use(response => {
return response.data;
}, reason => {
alert('小主,当前网络繁忙,请稍后再试~');
return Promise.reject(reason);
});
axios的请求、响应拦截器怎么使用?
- 基于拦截器进行公共部分提取
- 请求拦截器:发生在 “配置项准备完毕” 和 “发送请求” 之间
- 响应拦截器:发生在 “服务器返回结果” 和 “业务代码自己处理 .then” 之间
//请求拦截
axios.interceptors.request.use(config => {
// config对象包含的就是准备好的配置项,最后返回啥配置,就按照这些配置发请求
return config;
});
//响应拦截:如果成功就将结果返回给用户,如果失败,进行处理再返回
axios.interceptors.response.use(response => {
// 请求成功:把响应主体信息返回给业务层去使用
return response.data;
}, reason => {
// 请求失败:根据不同的失败原因做不同的提示
if (reason && reason.response) {
// @1 有返回结果,只不过状态码不对
let {status} = reason.response;
switch (+status) {//switch是做===比较
case 403:
alert('服务器不爱搭理你~~');
break;
case 404:
alert('你傻啊,地址都错了~~');
break;
case 500:
alert('服务器开小差了~~');
break;
}
} else {
// @2 请求超时或者中断
if (reason && reason.code === "ECONNABORTED") {
alert('请求超时或者被中断了~~');
}
// @3 断网
if (!navigator.onLine) {
alert('当前网络出问题了~~');
}
}
// 统一失败提示处理完,到业务代码处,我们还是要失败的状态,这样才能继续做一些自己单独想做的失败处理
return Promise.reject(reason);
});
fetch:ES6新增的方法
核心告别了XMLHttpRequest,基于新的通信机制实现可客户端和服务器的数据传输。
默认就是基于promise管理的。
不兼容IE浏览器(而且@babel/polyfill也没有实现他)、相关机制没有XMLHttpRequest完善。
用法:
fetch('http://localhost:9999/job/list',{
method:'GET',
headers:{},//请求头信息
//必须是字符串
// body:JSON.stringify({id:0})//请求体中的参数,GET/HEAD/OPtions/DELETE方法没有请求体,不能有body
}).then(function(response){
console.log(response);//获取的是一个响应信息的对象,看不到真正的响应体
return response.json(); //想要获取响应体的信息,需要调用对应格式的response.xxx()方法
}).then(function(value){
console.log(value);
})
注意点:
- GET/DELETE/OPTIONS/HEAD方法中不能存在body。
- fetch得到的结果是一个Promise对象,可以调用then方法PromiseResult是响应的信息,但找不到响应体信息。
- 想要获取响应体信息需要调用result对应数据格式的方法,比如想获取json格式的响应数据:result.json()/result.text()/result.formdata()/…
- result.json等格式获取方法只能使用一次,且只能有一种
axios和Fetch的区别?
- 相同点:他俩都是发送请求的
- 实现原理不同:axios是基于promise封装的ajax类库,fetch是ES6中浏览器原生的API
- 传参字段不同:
- axios的get请求参数放到params中,post请求体信息放到data里
- fetch的get请求参数直接跟在url后面,post请求体信息放在body里
- 环境支持程度:node环境中不支持fetch,需要引入node-fetch文件才能支持
- 功能差异:axios中的配置和拦截器等功能,fetch中都没有。