微信小程序 token 失效,自动重试机制

文章目录

    在需要用户登录的微信小程序中,需要处理 token 失效的问题。如果每个 wx.request 都去手动处理,非常麻烦。

    解决思路

    封装微信小程序自带的 wx.request,对返回的 http 状态码及错误码做区分处理。

    这里使用 ES6 的 Promise 进行封装。

    封装函数写在 app.js 中好,还是独立一个文件

    我觉得写在 app.js 中,就挺好,因为以后新项目可以直接复制 app.js 文件。

    如果独立一个文件,还需要同时复制 app.js 和另一个文件。

    一个实现范例

    app.js

    http: function({url = '', param = {}, type = 'json', ...other} = {}) {
    	wx.showLoading({title:'请求中...'});
    	return new Promise((resolve, reject) => {
    		wx.request({
    			url: this.globalData.host + url,
    			data: param,
    			header: {
    				'content-type': type == 'json' ? 'application/json' : 'application/x-www-form-urlencoded',
    				'Authorization': 'Bearer ' + wx.getStorageSync("token"),
    			},
    			...other,
    			complete: res => {
    				wx.hideLoading();
    				// 重新请求完token,再次执行后的请求在这里拦截
    				if (res.statusCode == 200) {
              resolve(res);
            } else if (res.statusCode == 401) {
              this.getNewToken().then(() => {
                this.http({url, param, type, ...other}).then(res => resolve(res));
              })
    				} else {
    					reject(res);
    				} // end of if
    			}
        }); // end of request
      }); // end of promise
    }, // end of http
    
    getNewToken: function() {
    	return new Promise((resolve, reject) => {
        wx.getSetting({
          success: res => {
            if (res.authSetting['scope.userInfo']) {
              wx.getUserInfo({
                success: res => {
                  this.globalData.userInfo = res.userInfo;
                  this.globalData.iv = res.iv;
                  this.globalData.encryptedData = res.encryptedData;
                  wx.login({
                    success: res => {
                      wx.request({
                        url: `${this.globalData.host}/api/login`,
                        method: 'POST',
                        data: {
                          code: res.code,
                          iv: this.globalData.iv,
                          encrypted_data: this.globalData.encryptedData
                        },
                        header: {
                          'content-type': 'application/json'
                        },
                        success: res => {
                          wx.setStorageSync('token', res.data.access_token);
                          resolve();
                        }
                      })
                    }
                  });
                }
              })
            } else {
              this.jumpToLogin();
            } // end of if
          }
        })
    	}) // end of promise
    }, // end of getNewToken
    
    jumpToLogin: function() {
      wx.removeStorageSync("token");  // 清理 token,防止前端登录状态显示错误
      wx.showModal({
        title: '提示',
        content: "请先登录",
        success (res) {
          if (res.confirm) {
            wx.switchTab({
              url: '/pages/user/user'
            })
          }
        }
      });
    }
    

    使用方法

    app.http({
      url: "/some_api",
      method: "GET",
    }).then(res => {
      console.log(res);
    });
    

    参考

    • https://www.jianshu.com/p/c3b07215aa72
    • https://juejin.im/post/5dcbafc4f265da4cfb513758
    • https://developers.weixin.qq.com/community/develop/doc/000c64d419cf78190ff748bb456400

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式