数据请求的几种方式(ajax、fetch、jQuery、axios),token过期自动刷新

数据请求的四种方式

1.ajax 数据请求:
原生js提供的(内置),核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回调地狱。

2.fetch 数据请求:
和ajax一样也是原生js提供的(内置),和ajax同级,使用promise形式,关注分离思想,但兼容性不太好,所以用的不是很多。

3. jquery数据请求:
封装原生的ajax请求,使用回调形式,可能回调地狱。(使用需要引入第三方库)

4. axios数据请求:
封装原生的ajax请求,使用promise的形式,并且可以在请求和响应阶段进行拦截。(使用需要引入第三方库)

关注点:使用原生ajax请求和使用axios请求

ajax 请求:
优点: 页面无刷新,用户体验好。异步通信,更加快的响应能力等等。
请求方式:get、post
1.get、post不同点:
(1).提交数据存储的位置不同 (安全性)
get请求将提交的数据拼接到URL后面?userName=lnj&userPwd=123456
(任何人可见)
post请求将数据放到请求头中(按f12=》Network=》header=》Form data)
(其他人不可见)
(2).提交数据大小限制不同
get请求对数据有大小限制 (适应于非敏感数据和小数据)
post请求对数据没有大小限制 (适应于敏感数据和大数据)

Ajax使用五个步骤:
   1.创建一个XMLHttpRequest对象
      var xmlhttp=new XMLHttpRequest();
   2.设置请求方式和请求地址(使用open(method,url,async)方法) 
       method:请求方式,get或者post。(默认为get)
          url:请求路径,文件在服务器上的位置
        async:是否为异步请求。(默认为true,异步请求)
   3.发送send() 请求
     若为post方式时需要使用setRequestHeader()来添加http头
   4.监听状态的变化
    每当readyState状态改变时,就会触发 onreadystatechange事件,执行回调函数。
     readyState存有XMLHttpRequest的5种状态。从 0 到 4 发生变化。
      0: 请求未初始化
      1: 服务器连接已建立
      2: 请求已接收
      3: 请求处理中
      4: 请求已完成,且响应已就绪
      
   5.处理返回的结果
     根据请求服务器返回状态码(status)
     大于200,小于300,或等于304,则表示请求成功, 否则服务器请求失败
     
    获取服务器中响应,使用XMLHttpRequest对象的responseText或responseXML属性。
      responseText : 获得字符串形式的响应数据。
      responseXML :  获得 XML 形式的响应数据。
 <button>发送请求</button>
 <script>
     window.onload=function () {
     var btn =document.querySelector("button");
     btn.onclick=function () {   
         //get请求
         //1.创建一个异步对象
         var xmlhttp=new XMLHttpRequest();
         //2.设置请求方式和请求地址
         xmlhttp.open("GET","07-Ajax-get.php"+"?userName=lnj&userPwd=123456",true);
         //3.发送请求
         xmlhttp.send();
         //4.监听状态的变化
         xmlhttp.onreadystatechange=function () {
                if (xmlhttp.readyState === 4) {
                   //5.处理返回的结果
                   if (xmlhttp.status>=200 && xmlhttp.status<300 ||xmlhttp.status===304){
                       console.log(xmlhttp.responseText); //输出服务器响应的内容
                    }else{
                        console.log("没有接收到服务器的数据");
                    }
                }
             }
         }
               
         //post请求    
         var xmlhttp=new XMLHttpRequest();
         xmlhttp.open("POST","10-Ajax-post.php",true);
         //post方式时需要使用setRequestHeader()来添加http头,将该内容放在设置请求与发送请求之间;
         xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
         //发送请求, 将要提交的数据放在send()中;
         xmlhttp.send("userName=liu&userPwd=654321");
         xmlhttp.onreadystatechange=function () {
            if (xmlhttp.readyState === 4) {  //请求完成时响应;
              if (xmlhttp.status>=200 && xmlhttp.status<300 ||xmlhttp.status===304 ){
                        console.log(xmlhttp.responseText);
                    }else{
                        console.log("没有接收到服务器的数据");
                    }
                }
            }
         }
      }
    </script>

axios请求:
优点: Axios是轻量级的库,支持promise,可以拦截请求和响应等等。

安装: npm install axios
引入:import axios from “axios”

1.axios的基本使用:
axios()返回一个promise对象

//get
axios.get('http://123.207.32.32:8000/home/data?type=sell&page=3')
  .then((response)=> { console.log(response)})
  .catch((error)=> {console.log(error)})
  
可以通过向 axios 传递相关配置的方式来创建请求,如下:
axios({
    methods:"get"      //请求方式不写就默认为get请求     
    url:"http://123.207.32.32:8000/home/data?type=sell&page=3",
 }).then(res=>{  //数据请求成功,res为成功数据
    console.log(res);
 }).catch((err)=>{
    console.log(error);
 )
//可以将url拆分开,将后面的参数单独放在params中
axios({
   methods:"get" 
   url:"http://123.207.32.32:8000/home/data",
   params:{
     type:"sell",
     page:3
   }
 }).then(res=>{  //请求成功   
   console.log(res);
 })

//post
axios({
  method: 'post',
    url: '/user/12345',
   data: {   //post传递参数
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
}).then(function (response) {
     console.log(response);
  }).catch(function (error) {
     console.log(error);
  });
  

2.axios发送并发请求

axios.all([ axios(),axios() ]) .then(results => { … })

 axios.all([       //第一个请求
       axios({
           url:"http://123.207.32.32:8000/home/multidata"
       }),
       axios({     //第二个请求
           url:"http://123.207.32.32:8000/home/data",
           params: {
               type:"sell",
               page:5
             }
        })
    ]).then(results => {  //results为数组,存是两次请求成功的数据
          console.log(results);     //将整个数组输出
          console.log(results[0]);  
          console.log(results[1]);
    })

3.axios全局配置

在axios请求中,可以设置超时时间

 axios.all([
     axios({
          // url:"http://123.207.32.32:8000/home/multidata",  url分解为
          baseURL:"http://123.207.32.32:8000",
          url:"/home/multidata",
          timeout:5000  //超时时间
       }),
    axios({
          url:"http://123.207.32.32:8000/home/data",
          timeout:5000 
       })
     ]).then(results => {console.log(results)})

//若每个axios的超时时间和baseURL都相同 就可以进行全局配置,让所有的axios请求都会使用全局配置发送请求。(公共的对象放在全局配置里面)

//全局配置内容
axios.defaults.baseURL="http://123.207.32.32:8000"
axios.defaults.timeout=5000
 axios.all([
      axios({
         url:"/home/multidata",
       }),
      axios({
         url:"/home/data",
       })
    ]).then(results => {console.log(results) })

4.创建axios实例
有时候请求不想用全局配置的内容,则我们可以创建axios实例,在该axios实例中全局配置,则只在该实例内有效。

 const instance = axios.create({
     baseURL:"http://123.207.32.32:8000",
     timeout:5000
 })
 
// 在instance实例中发送请求,则会使用instance实例的axios配置。
 instance({
   url:"/home/multidata"
 }).then(res => {
   console.log(res);
 })
// 
 instance({
   url:"/home/data",
   params:{
     type:"pop",
     page:1
   }
 }).then(res=>{
   console.log(res);
})

5.封装一个request模块
为了可以让主页面的代码尽量少一些,可以封装一个request模块,在模块中封装好axios的网络请求,然后直接引入使用。

request模块中封装:
(推荐方式2)

//方式1:
 export function request(config ,success ,failure) {
   //1.创建axios实例
   const instance = axios.create({
     baseURL:"http://123.207.32.32:8000",
     timeout:5000
   })
   //2.发送网络请求
   instance (config)  //config为传进来的参数。
     .then(res =>{
       console.log(res);
      success(res);  //success为传进来的函数,则res外函数的参数。
     }).catch(err=>{
       console.log(res);
       failure(res);  //传参
     })
 }
//方式2:
 export function request(config) {
   //1.创建axios实例
   const instance = axios.create({
      baseURL:"http://123.207.32.32:8000",
      timeout:5000
   })
 return instance (config)
//axios返回的是一个promise对象,return instance实例, 所以prmose中的res数据为该实例。 
//这里是直接将instance实例返回给主页面,然后在主页面中进行操作。
}

主页面中:

//方式1:
 request({            //为request()传过去3个参数。
   url:"/home/multidata"
 },res =>{          //则这里res是success(res)中res,是拿到的结果
   console.log(res);
 },err=>{
   console.log(err);
})

//方式2:
//传入url, 返回instance实例, 然后在该页面对结果进行处理
 request({  
   url:"/home/multidata"
 }).then(res=>{
    console.log(res);
 }).catch(err=>{
     console.log(err);
 })

6.拦截器:

拦截axios的请求和响应,可以在请求数据前和拿到响应返回数据前添加一些代码,然后进行相应的处理。可以转换请求数据和响应数据

request模块中封装:

export function request(config) {
//1.创建axios实例
  const instance = axios.create({
    baseURL:"http://123.207.32.32:8000",
    timeout:5000
  })
  
//2.axios的请求拦截器, 拦截的是instance请求中的config内容。
  instance.interceptors.request.use(config =>{    
    //这里的config包含每次请求的内容,如请求头、url、传参data等等。
    console.log(config);
    //请求拦截后会做什么事情???
    //1.比如:config中的一些信息,不符合服务器的要求, 对信息修改会转化
    //2.比如:某些网络请求(登录..),必须携带一些特殊的信息,则将它拦截,然后判断一下,如果没带特殊信息,则给它提示
    return config   
    //请求拦截,操作后返回config,不然请求拦截了服务器不会响应,拿不到结果。
  },err => {
    console.log(err);
  })
  
//3.axios的响应拦截器, 拦截的是服务器返回的结果res
  instance.interceptors.response.use(res=>{
    //这里的res包含服务器响应的data、响应头、状态码,配置等等。
    console.log(res);
    //拦截后,进行相关操作...
    return res.data              
    //若需要数据,则可以只返回拦截内容中的data就可以了
  },err=>{
    console.log(err);
  })

  return instance (config)
}

axios的请求拦截器中的config对象中内容
config对象内容
axios的响应拦截器中的res对象中内容
在这里插入图片描述

主页面中:

request({
  url:"/home/multidata"
}).then(res=>{
   console.log(res);
}).catch(err=>{
   console.log(err);
})

扩展:
HTTP请求报文由3部分组成 =>(请求行+请求头+请求体)
请求头 存放通知服务器有关于客户端请求的信息,一般用来存放一些cookie,token等信息(属性:属性值)
常见的请求头有:
cookie : 浏览器端cookie
Accept :告诉服务端 客户端接受什么类型的响应。
Authorization HTTP授权的授权证书 ——》用来设置token
Referer:表示这个请求是从哪个URL过来的
application/json : JSON数据格式
Connect-Type : 显示此HTTP请求提交的内容类型。一般只有post提交时才需要设置该属性。等等。
响应头 Response Header
常见的响应头有:
Accept-Ranges:表明服务器是否支持指定范围请求及哪种类型的分段请求
Expires:响应过期的日期和时间
常见的响应码有:
1. 200 OK
2. 303 See Other ,把redirect到其它的页面
3. 404 Not Found ,责任在客户端 ,即找不到页面
4 .5xx 处理发生错误,责任在服务端,如服务端抛出异常,路由出错等

7.拦截器实例:

扩展:token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,来进行验证客户端的权限等。
登录token的验证流程:
1.客户端使用用户名跟密码请求登录,服务端收到请求,去验证用户名与密码
3.验证成功后,服务端会想客户端返回一个 token
4.客户端收到 token后把它存在浏览器的 sessionStorage 或者 localStorage 中
5.客户端每次向服务端请求资源时携带token验证,(获取 localStorage中存储的token,将它放在请求头中)
6.服务端收到请求,然后去验证客户端请求里面带着的 token,如果验证成功,就向客户端返回请求的数据

1.在登陆的时候后台会给一个token码,前台将其存储在浏览器的cookie,localstroage或localsession中

   login(){
            axios.post('/user/login',this.user).then((res)=>{
                localStorage.setItem('token',"Bearer "+res.data.res.token)
                //需要在token的前边拼接字符串’Bearer '+,固定格式
            })
        }

发起请求时带上token,看用户是否有权限

const token = window.sessionStorage.getItem('cat_token')   //获取存储的token
axios.get('path', {
  headers: {
    authorization: `Bearer ${token}`,  //将token放到请求头中,Authorization属性存放验证
  },
});

拦截器中处理token
请求时将token放入请求头,响应是若token过期,则根据返回的错误码提示

// http request 拦截器
axios.interceptors.request.use(
  config => {
    if (localStorage.token) { //判断token是否存在
      config.headers.Authorization = localStorage.token; //将token放入请求头
    }
    return config;
  },
  err => {
    return Promise.reject(err);
  }
);
// http response 拦截器
axios.interceptors.response.use(
  response => {
    if (response.data.errno === 999) {  //过期服务器返回错误码
      router.replace('/');
      console.log("token过期");
    }
    return response;
  },
  error => {
    return Promise.reject(error);
  }
);
export default axios;

(注:若有不需要验证的页面 或者 没有权限的设置为不能进入该页面 则可以在路由配置中限制)

点击,token参考文档,axios拦截器,实现token认证

token过期处理:
1.返回到登录页面 ,重新请求登录返回token
2.通过时间判断是否快过期,然后自动刷新token,若刷新失败返回登录页面。
自动刷新:请求前用refleshToken()接口来请求,返回新的token,再用新的token将旧的替换,不影响后面操作。

什么时候自动刷新???
在登录返回token值时前台获取当前时间戳,设置距离过期还有多长时间时自动刷新,
(登录的时候后端返回一个token过期时间(秒),转换成时间戳保存下来。在拦截器中获取当前的时间,进行对比。点击案例)

定时刷新token
定期刷新token,请求与响应中的处理


版权声明:本文为qq_45700583原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。