收藏
回答

小程序wxRequest封装一个无痛刷新token方法?

当token过期后就去获取新的token,但要阻止同一个页面多个异步请求,在请求到新的token前,把请求任务放在队列,新token生成后再执行任务队列的请求,大概咋写啊,我怎么写都不对,就是怎么回调任务队列的请求

这是我现在的代码,大概思路是这样子,但是好像没有效果


var BASE_URL = 'https://www.****.com'

// 定义一个flag 判断是否刷新Token中
let isRefreshing = false;
// 保存需要重新发起请求的队列
let retryRequests = [];


class Request {
    /**
     * Request请求方法
     * @param  {String} url    链接
     * @param  {Objece} params 参数
     * @param  {Boolean} isToken  是否携带token
     * @return {Promise}       包含抓取任务的Promise
     */


    getApi(url, params, isToken, method) {
        if (isToken === undefined) isToken = true;
        if (method === undefined) method = 'GET';
        let token = wx.getStorageSync('logintoken') || '';
        let that = this;


        return new Promise((resolve, reject) => {
            //请求封装
            wx.request({
                url: `${BASE_URL}${url}`,
                method: method,
                data: params,
                header: {
                    'Content-Type': 'application/json',
                    "token": token,
                },
                success: res => {
                    if (res.statusCode == 200) {
                        const code = res.data.code || 200;
                        if (code == 200) {
                            resolve(res);
                        } else if (code == 10245) {
                           
                            // 返回10245表示token过期  多个异步请求 token 刷新处理
                            console.log('token过期了')
                            console.log('isRefreshing 状态',isRefreshing)
                            console.log('retryRequests 数组',retryRequests)


                            if(!isRefreshing){
                                // 改变flag状态,表示正在刷新Token中 不让其他请求进来
                                isRefreshing = true

                                                // 去获取新token 
                                 getApp().GetLogin().then(res=>{
                                        // 遍历执行需要重新发起请求的队列
                                    // retryRequests.forEach(cb => cb())
                                    // retryRequests =[]
                                })
                                .finally(() => {
                                    // 请求完成后重置flag
                                    isRefreshing = false;
                                })


                            }else{
                                // 正在刷新token,返回一个未执行resolve的promise
                                // 把promise 的resolve 保存到队列的回调里面,等待刷新Token后调用
                                // 原调用者会处于等待状态直到 队列重新发起请求,再把响应返回,以达到用户无感知的目的(无痛刷新)
                            
                                // 将resolve放进队列,用一个函数形式来保存,等token刷新后直接执行
                                
                                // retryRequests.push(()=>that(url, params, isToken, method));
                            }
                       
                        } else {
                            wx.showToast({
                                title: res.data.msg || '服务器出错',
                                icon: 'none',
                                duration: 1200,
                                mask: true
                            });
                            reject(res.data);
                        }
                    } else {
                        wx.showToast({
                            title: '[' + res.statusCode + '] 服务器出错,请重试',
                            icon: 'none',
                            duration: 1200
                        });
                        reject(res);
                    }


                },
                fail: err => {
                    console.log(err)
                    wx.showToast({
                        title: '网络错误',
                        icon: 'none',
                        duration: 1200
                    });
                    reject(err);
                },
                complete: () => {


                }
            });
        });
    }


}


let request = new Request();


module.exports = {
    request: request.getApi,
    url: BASE_URL
}


最后一次编辑于  2022-03-31
回答关注问题邀请回答
收藏

4 个回答

  • brave
    brave
    2022-03-31

    参考下 https://developers.weixin.qq.com/community/develop/article/doc/000cac14f44e70059368f3c1b5bc13

    2022-03-31
    有用 3
    回复
  • 冯志辉
    冯志辉
    2022-04-06

    TOKEN过期前获取存放REDIS就好了

    2022-04-06
    有用 1
    回复
  • 那一抹笑😃 穿透阳光
    那一抹笑😃 穿透阳光
    2022-03-31

    wx.pro.request = (options) => {

     return new Promise((resolve, reject) => {

    let req = {

         url: wx.getStorageSync("serverurl"+ options.url,

            method: options.method || 'GET',

           header: {Authorization: 'Bearer ' + wx.getStorageSync("token")},

           success: (res) => {

             if (res.statusCode == 401 && requestNumber <= 3{

                 login().then((log) => {

                    requestNumber++;

                        if (log.results{wx.setStorageSync("token", log.results.token); }

                        resolve(wx.pro.request(options))

                  })

             } else {

                 resolve(getData(res))

              },

         fail: (err) => {

            reject(getData(err));

          }

      };

     if (options.data{

        req.data = options.data;

        req.header['content-type'= 'application/json';

        }

       wx.request(req);

     });

    };

    2022-03-31
    有用
    回复 1
    • 那一抹笑😃 穿透阳光
      那一抹笑😃 穿透阳光
      2022-03-31
      let requestNumber = 0; //登录接口请求次数,防止接口报错,无限请求

      function login() {
          return wx.pro.login().then((res) => {
              return wx.pro.request({
                  method: 'GET',
                  url: 'api/miniprogram/auth',
                  data: {
                      code: res.code
                  },
                  header: {
                      'content-type': 'application/json';
                  },
              })
          })
      }
      2022-03-31
      回复
  • 拾忆
    拾忆
    2022-03-30

    token刷新要放在服务端处理不是放在小程序端处理。

    服务端定期刷新token放在数据库或者redis供小程序使用。

    2022-03-30
    有用
    回复
登录 后发表内容