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

更新日期: 2020-05-13 阅读次数: 9389 字数: 414 分类: 微信小程序

在需要用户登录的微信小程序中,需要处理 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 聊聊, 查看更多联系方式