文章目录
axios学习笔记
HTTP相关
HTTP请求交互的基本过程
HTTP请求报文
- 请求行 method、url
- 多个请求头
- Host:主机
- Cookie:携带cookie数据
- Content-Type请求体的内容类型:
application/json
或者application/x-www.form.urlencoded
- 请求体 get请求没有请求体,通过Content-Type告诉请求体的数据类型
{“username”:”tom”,”pwd”:123}
或者username=tom&pwd=123
顺序与Content-Type顺序对应
HTTP响应报文
- 状态行
- status statusText
- 多个响应头
- Content-Type响应体的内容类型:text/html;charset=uft-8 Set-Cookie:BD_CK_SAM=1;path=/
- 响应体
- html 文本/json 文本/js/css/图片…
post请求体参数格式
- Content-Type:application/x-www.form.urlencoded
例如:username=tom&pwd=123 - Content-Type:application/json
例如:{“username”:”tom”,”pwd”:123} - Content-Type:multipart/form-data
用于文件上传请求
常用请求类型
- GET:从服务器端读取数据
- POST:向服务器端添加新数据
- PUT:更新服务器端已有数据
- DELETE:删除服务器端数据
XHR的理解和使用
XHLHttpRequest(XHR)对象可以与服务器交互,获取数据而无需刷新整个页面,不影响用户的操作的情况下更新页面的局部内容(手动写DOM更新代码)。
区别ajax请求与一般的http请求
1.ajax请求是一种特别的http请求
2.浏览器端发请求:只有XHR或fetch发出的才是ajax请求
3.浏览器端接收响应:
一般请求:浏览器一般会直接显示响应体数据,也就是我们常说的刷新/跳转页面,在地址栏写地址跳转
ajax请求:浏览器不会对界面进行任何更新操作,可以获取数据,手动操作数据
API
属性 | 描述 | 备注 |
---|---|---|
XMLHttpRequest() | 创建XHR对象的构造函数 | 下面的属性和方法,基本都是XHR实例上的属性和方法 |
status | 响应状态码 | |
statusText | 响应状态文本 | |
readyState | 请求的状态 | 0:初始 1:open()之后 2:send()之后 3:请求中 4:请求完成 |
onreadystatechange监视回调函数 | 绑定readyState改变的监听 | on…当…时执行 |
responseType | 指定响应数据类型 | |
response | 响应体数据,类型取决于responseType | |
timeout | 指定请求超时时间,默认0代表没有限制 | |
ontimeout | 当超时时执行的回调函数 | |
onerror | 绑定请求网络错误的监听 | 当请求网络出错时调用 |
open(method,url[,async]) | 初始化一个请求 | 默认async:true,参数是请求行 |
send(data) | 发送请求 | 参数为字符串,可以是json对象字符串,也可以是urlencoded格式字符串 |
abort() | 中断请求 | 中断是发出请求,还没结束的请求 |
getResponseHeader(name) | 获取指定名称的响应头值 | 请求成功后,数据已经在发送请求的XHR对象的response里 |
getAllResponseHeaders(): | 获取所有响应头组成的字符串 | |
setResponseHeaders(name,value) | 设置请求头 |
发送JSON格式的请求体,需要加请求头
xmr.setRequestHeader('Content=Type','application/json;charset=utf-8'
发送urlencoded格式的请求体,也需要加请求头
xmlHttpRequest.setRequestHeder("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
XHR的ajax封装(简单版axios)
axios库暴露的axios是一个函数,函数的参数是配置对象optionA。配置对象的属性名和作用都是固定的。
特点
1.函数的返回值为promise,成功的结果为response,失败的结果为error
2.能处理多种类型的请求:GET/POST/PUT/DELETE
3.参数为配置对象
{
url:"",//请求地址
method:"",//请求方式
params:{},//GRT/DELETE请求的query参数
data:{},//POST或DELETE请求的请求体参数
}
axios里面的params参数配置的是GRT/DELETE请求的query参数、
axios里面的data配置的是POST/PUT请求的请求体参数
data有两种格式,对象为json格式,字符串为urlencoded格式
4.响应json数据自动解析为js
5.response只实现了data,status,statusText
6.put请求提交的是请求体参数,delete提交query参数
代码
1.先处理参数,有默认值的设置默认参数
2.执行异步ajax请求,如果请求成功了调用resolve()
,如果请求失败了调用reject()
2.1 创建xhr对象new XMLHttpRequest()
2.2 初始化请求xmr.open()
2.3 发送请求xmr.send()
发送请求。参数为字符串,可以是json对象字符串,也可以是urlencoded格式字符串
function axios({
url,
method="GET", //设置默认值
parmas={},//默认空对象
data={}//设置默认值
}) {
//返回一个Promise对象
return new Promise((resolve, reject) => {
//处理query参数,拼接到url
let queryString='';
Obeject.keys(params).forEach(key=>{
queryString+=`${key}=${parmas[key]}&`
})
if (queryString){
//去掉最后的&
queryString = queryString.substring(0,queryString.length-1)
//拼接
url += "?"+queryString
}
//处理method为大写,传进来的可能是小写
method = method.toUpperCase()
//1.执行异步ajax请求
//创建xhr对象
const request = new XMLHttpRequest();
//初始化请求(异步)
request.open(method,url,true)
//绑定状态改变的监听,send是异步的,所以绑定监听写在send后面也可以
request.onreadystatechange = function () {
//如果请求没有完成,不需要做处理
if (request.readyState!==4){
return
}
//请求完成了可以获取状态码了
//如果响应状态码在[200,300)之间代表成功,否则失败
const {status,statusText} = request;
if (status>=200&&status<=299){
//2.1如果请求成功了,调用resolve()
//准备结果response对象
const response = {
//服务器返回的是JSON数据需要转换成对象
//响应json数据自动解析为js的对象/数组
data:JSON.parse(request.response),
status,
statusText,
}
resolve(response)
}else {
//2.2如果请求失败,调用reject()
reject(new Error(`request error status is ${status}`))
}
}
switch (method){
case "GET"||"DELETE" :
//get的参数通过url传
request.send();
break;
case "POST"||"PUT":
//发送JSON请求体的数据
request.setRequestHeader("Content-Type","application/json;charset=utf");
request.send(JSON.stringify(data));
break;
}
})
}
axios的理解和使用
axios是什么?
基于promise的异步ajax请求库
axios的特点
1.支持请求/响应拦截器 ★
2.浏览器端(ajax请求)/node端(一般的HTTP请求)都可以使用
3.支持请求取消
4.批量发送多个请求 --> promise.all也可以
5.请求/响应数据转换 --> 使用时写的是对象,axios自动转换成了json。接受时axios也自动将json转换为了对象
axios的post请求头默认是application/x-www-form-urlencoded
如果data是对象,默认Json。
指定默认配置
设置默认的基础URL,假设需要向http://localhost:3000/post url直接"/post"即可,会拼接在默认路径上
//方法1
axios.default.baseURL='http://localhost:3000'
//方法2,后续用requestAxios当作原来的axios使用,都是axios的实例。
const requestAxios = axios.create({
baseURL:"http://localhost:3000",
})
axios.create(config) axios二次封装
自定义配置新建一个新的axios实例,新axios没有取消请求和批量发请求的方法,其他所有语法都是一致的。
const instance = axios.create({
baseURL:"http://localhost:3000"
})
//使用instance发请求
instance({
url:"/posts" //请求端口3000
})
这个语法的用处:
需求:项目中有部分接口需要的配置与另一部分接口需要的配置不太一样
解决:创建2个新的axios,每个都有自己特有的配置,分别应用到不同要求的接口请求中
axios.default.baseURL = "http://localhost:4000"
axios({
url:"/posts" //请求的端口4000
})
const instance = axios.create({
baseURL:"http://localhost:3000"
})
//使用instance发请求
instance({
url:"/posts" //请求端口3000
})
axios.interceptors 拦截器
- 请求拦截器 axios.interceptors.request.use(callback)
- 响应拦截器 axios.interceptors.response.use(callback)
拦截器是回调函数,参数有两个成功的回调和失败的回调
axios.interceptors.request.use(config=>{
console.log("request interceptor1 ");
//拦截请求,处理请求之后,必须要返回该配置,若不返回相当于axios请求没有添加配置
return config
},error=>{//不常用
console.log("request interceptor1 err");
return Promise.reject(error); //将错误传递下去
})
axios.interceptors.request.use(config=>{
console.log("request interceptor2 ");
return config
},error=>{
console.log("request interceptor2 err");
return Promise.reject(error)
})
axios.interceptors.response.use(response=>{
console.log("response interceptor1 ");
return response
},error=>{
console.log("response interceptor1 err");
return Promise.reject(error)
})
axios.interceptors.response.use(response=>{
console.log("response interceptor2 ");
//拦截response结果处理之后,要返回结果
return response
},error=>{
console.log("response interceptor2 err");
return Promise.reject(error)
})
axios.get("http://localhost:3000/posts").then(response =>{
console.log("response data");
}).catch(error=>{
console.log("response error");
})
/*
输出
request interceptor2
request interceptor1
response interceptor1
response interceptor2
date ....
*/
说明
1.请求拦截器后添加先执行,响应拦截器先添加后执行 需要注意
2.拦截请求,处理请求之后,必须要返回该配置,若不返回相当于axios请求没有添加配置
3.拦截response结果处理之后,要返回结果。
取消请求
1.excutor执行器函数是同步执行的,参数是用于取消当前请求的函数
2.当取消当前请求的函数被调用时,该请求会进入失败的流程,请求失败的error是Cancel对象类型,Cancel里面有message属性
let cancel //保存用于取消请求的函数
axios.get("/user",{
cancelToken:new axios.CancelToken(function excutor(c){
cancel = c; //准备发请求时先把函数取消当前请求的函数存储起来
}).then(response =>{
cancel = null; //如果请求完成就不要取消请求了
},error =>{
cancel = null;
})
})
应用场景:如果发送请求2的时候,发现请求1还没有完成则取消请求1
let cancel //保存用于取消请求的函数
function getProducts1(){
if (typeof cancel === "function"){
cancel("这里可以传消息提示")
}
axios.get("/user",{
cancelToken:new axios.CancelToken(
//执行器回调,同步进行
c => {//c是用于取消当前请求的函数
cancel = c
}
)
}).then(response =>{
cancel = null
},error =>{ //为什么要区分,因为这里是异步执行的,如果此时cancel是等于请求2的取消函数,不分区执行的时候cancel会被置空,cancel为null不是为请求2的取消函数,这样会出问题
if (axios.isCancel(error)){ // 取消请求
//cancel = null 这个必须要区分!!!
console.log("请求1被取消了",error.message);
}
else{ //请求本身出错
cancel = null
console.log(error);
}
})
}
function getProducts2(){
if (typeof cancel === "function"){ //在准备发请求前,取消未完成的请求
cancel("这里可以传消息提示")
}
axios.get("/user/1",{
cancelToken:new axios.CancelToken(
c => {cancel = c}
)
}).then(response =>{
cancel = null
},error =>{
if (axios.isCancel(error)){
console.log("请求2被取消了",error.message);
}
else{
cancel = null
console.log(error);
}
})
}
通过拦截器将代码进行改进
//添加请求拦截器
axios.interceptors.request.use(config=>{
if (typeof cancel === "function"){
cancel("这里可以传消息提示")
}
//添加一个cancelToken的配置
config.cancelToken =new axios.CancelToken(
c => {
cancel = c
})
return config
})
//添加响应拦截器
axios.interceptors.response.use(
respose=>{
cancel = null
return respose
},
error =>{
if (axios.isCancel(error)){
console.log("请求取消了",error.message);
//中断promise链接,目的是:当请求失败时,请求函数本身只处理请求失败的情况,不处理请求取消的情况
return new Promise(()=>{})
}
else{
cancel = null
//将错误继续向下传递
// throw error
return Promise.reject(error)
}
})
let cancel
function getProducts1(){
axios.get("/user").then(response =>{
//其他数据响应
},error =>{
//只需要处理请求失败
})
}
function getProducts2(){
axios.get("/user/1").then(response =>{
//其他数据响应
},error =>{
//只需要处理请求失败
})
}