Request页面的代码逻辑整理

4 篇文章 0 订阅

封装请求基地址:简单流程

1·在src目录下 放上一个专门写请求相关的文件夹
2·然后在里面新建一个专门放用户请求的use.js
3·用axios发送请求
4·在use.js文件夹里导入request
5·并且根据接口文档 写请求
6·然后把这个请求封装成一个函数,这个函数里需要传入两个参数
7·这两个参数 都放在data数据里 所以可以直接申明需要的数据是data

 设置请求拦截器并设置请求头

http://t.csdn.cn/vSDg0 

一. 配置 axios
1. static 文件夹中创建一个 api 文件夹,api 文件中创建一个 http.js 文件
2. 配置 http.js 文件
3. main.js 中引入 http.js 文件
二. 组件中发送接口请求时,会发现报跨域错误
1. 配置 config 文件夹中的 index.js 文件
2. 修改 http.js 文件中的 默认接口
3. 修改之后的 http.js
4. npm run dev重启项目,发现接口正常请求。
三. 总结 axios 拦截器(请求和响应)
 

 

添加响应拦截器

首先在vue项目中src文件夹下新建request文件夹,关于接口封装文件都放在request文件夹中。
然后在request文件夹中创建index.js,url.js,api.js三个js文件。

url.js文件主要放置项目中api请求域名和打包的域名(包括测试环境,预生产环境,生产环境)
注意:index.js文件主要对axios封装,添加请求拦截器和响应拦截器

          api.js文件主要放置项目中的接口 (post和get两种参数不同,注意区别data和params)

token过期问题处理(为啥?)

      后端为了安全,token一般存在有效时间,当token过期,所有请求失效!

解决方案:
1)在请求发起前拦截每个请求,判断token的有效时间是否已经过期,若已过期,则将请求挂起,先刷新token后再继续请求。
优点: 在请求前拦截,能节省请求,省流量
缺点: 需要后端额外提供一个token过期时间的字段;使用了本地时间判断,若本地时间被篡改,特别是本地时间比服务器时间慢时,拦截会失败
使用方法:axios.interceptors.request.use() 这个请求前拦截方法

无感刷新

【【JS春招面试题】有没有做过无感登录?token无感刷新】https://www.bilibili.com/video/BV1V24y177wm?vd_source=19ead775cfe547544ef450f49070db30
春招面试——前端

 

        // 这个时候把获取用户信息这个请求再发了一次
        // 在请求拦截器中,拦截器return什么,浏览器就拿到什么
        return request(error.config)

refresh_token过期处理(直接看图)

 

分析:

当token失效或即将失效时, 重新获取新的token, 但因为ajax是异步的, 请求新的token是需要一定时间, 此时若是有新的请求接口, 就会出现问题

在网上查询资料后, 一般有两种方法可以实现无痛刷新token机制:

  • 在请求拦截中, 拦截刷新token时, 将额外接口缓存, 刷新成功后在重新发送请求
  • 在响应拦截中, 将额外接口缓存, 刷新成功后在重新发送请求

 

// 创建axios实例
const service = axios.create({
    withCredentials: false, // 请求不带cookie
    baseURL: baseURL, // api 的 base_url
    timeout: timeout // 请求超时时间
});


// 请求拦截器没有做处理
service.interceptors.request.use(config => {
    ...
    return config
})

// 是否正在刷新的标记 -- 防止重复发出刷新token接口
let isRefreshing = false;
// 判断token是否失效: return: true为过期
function isOAverdue() {
    // 当离过期时间还有半小时时, 也判断为过期
    // getTokenItem('time'): 获取存入localStorage的过期时间
    return Math.floor((Date.now() - getTokenItme('time')) / 1000) + 30 * 60 > 
        getTokenItme('expires_in');
}
// 失效后同时发送请求的容器 -- 缓存接口
let subscribers = [];
// 刷新 token 后, 将缓存的接口重新请求一次
function onAccessTokenFetched(newToken) {
    subscribers.forEach((callback) => {
        callback(newToken);
    });
    // 清空缓存接口
    subscribers = [];
}
// 添加缓存接口
function addSubscriber(callback) {
    subscribers.push(callback);
}

// 响应拦截器
service.interceptors.response.use(
    response => {
        // 当response.data.re为401, 则判断token已经过期
        // /oauth/token为刷新token的接口, 需要排除掉 
        if ((isOAverdue() || response.data.ret === 401) && !response.config.url.includes('/oauth/token')) {
            if (!isRefreshing) {
                isRefreshing = true;
                // 将刷新token的方法放在vuex中处理了, 可见下面区块代码
                store.dispatch('refreshToken').then((res) => {
                    // 当刷新成功后, 重新发送缓存请求
                    onAccessTokenFetched(res);
                }).catch(() => {
                    // 刷新token报错的话, 就需要跳转到登录页面
                    window.location = '/#/guide/login';
                }).finally(() => {
                    isRefreshing = false;
                });
            }
            // 将其他接口缓存起来 -- 这个Promise函数很关键
            const retryOriginalRequest = new Promise((resolve) => {
                // 这里是将其他接口缓存起来的关键, 返回Promise并且让其状态一直为等待状态, 
                // 只有当token刷新成功后, 就会调用通过addSubscriber函数添加的缓存接口, 
                // 此时, Promise的状态就会变成resolve
                addSubscriber((newToken) => {
                    // 表示用新的token去替换掉原来的token
                    response.config.headers.Authorization = `bearer ${newToken}`;
                    // 替换掉url -- 因为baseURL会扩展请求url
                    response.config.url = response.config.url.replace(response.config.baseURL, '');
                    // 用重新封装的config去请求, 就会将重新请求后的返回
                    resolve(service(response.config));
                });
            });
            return retryOriginalRequest;
        }
        // ========================
        
        // .... 省略其他代码.....
    }
    
    // vuex中刷新token方法
    async refreshToken({ commit }) {
        // getTokenItem('refresh_token): 获取刷新token
        try {
            let res = await refreshToken(getTokenItem('refresh_token));
            const data = res.access_token;
            newSetToken(res);
            return data;
         } catch(e) {
            return '刷新token出错';
         }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值