微信小程序-授权登录处理思路整理

微信小程序的授权思路我初步是这么设想的

每个页面的onLoad方法配置一个统一的initHandler工具方法,这个方法先调用一个公共方法getLoginInfo。

这里,校验是否存在登录信息,没有的话去重新登录。

登录之后,有一个让人纠结的问题。登录信息的token和sessionid,是应该放在storage里还是应该放在全局变量里呢?

登录信息放在storage还是放在全局变量?

  • 放在storage:涉及到容易出现登录信息过期的问题。优点是可以长期记录登录信息和状态
  • 放在全局变量:不存在登录信息过期的问题。缺点是每次进入小程序都要调取登录接口。

这里我是比较倾向于放在全局变量。我的理由如下:

  • 1.对小程序来说,我推测应该是弹出授权框一次之后,一旦确认授权,在一段时间内是不需要再次弹出的。也就是说 可以直接拿到微信数据然后去调用登录接口。这步是前提,因为不可能让用户每次进来都弹窗。
  • 2.对于请求次数,放在全局变量,每次进入都调用一次登录。虽然每次进入都 需要调用,但是整个小程序也只调用一次,问题不大。如果放在storage,那么我只能通过判断内存中是否有登录信息,如果有的话就拿登录信息去调用接口。 这时候,对于单次打开小程序的过程,两种方法区别不大。对于第N次进入小程序的操作,由于目前所做的小程序并不是频次太高的业务,二次进入的时候token 过期的可能性比较大。这时候如果采用storage,就涉及到调接口,返回授权失败,然后清除登录信息,重新登录。比较于上一种方法,周期反而更长。

这里先用全局变量处理。方法如下。

let app = getApp()
/****************************
 *小程序  调登录 获取token 和 session
 */
export const getLoginInfo = function () {
  return new Promise((resolve, reject) => {
    // 判断是否有token和session
    if (app.globalData.userInfo.sessionId && app.globalData.userInfo.token ) {
      // 存在token和session
      resolve('已登陆')
    } else {
      // 不存在token和session
      let code = ''
      wx.login({
        success: function (res) {
          if (res.code) {
            code = res.code
            // 查看是否授权
            wx.getSetting({
              success: function (res) {
                if (res.authSetting['scope.userInfo']) {
                  // 已经授权,可以直接调用 getUserInfo 获取头像昵称
                  wx.getUserInfo({
                    success: function (res) {
                      let obj = {
                        code: code,
                        rawData: res.rawData,
                        signature: res.signature,
                        encryptedData: res.encryptedData,
                        iv: res.iv
                      }
                      //发起网络请求
                      wx.request({
                        url: 'http://aaaaaaaaa/login/login',
                        data: obj,
                        success: function (res) {
                          app.globalData.userInfo.sessionId = res.data.data.sessionId
                          app.globalData.userInfo.token = res.data.data.token
                          resolve({code: '00'})
                        }
                      })

                    }
                  })
                }
              }
            })

          } else {
            console.log('登录失败!' + res.errMsg)
          }
        }
      });

    }
  })
}

在页面中,方法如下

onLoad: function (options) {
    this.initDom()
    this.initHandler()
},
initHandler () {
    getLoginInfo().then((res) => {
      console.log(res)
      this.initRemoteHandler()
    })
},

这要,每个页面初始化的时候,都可以先校验登录状态,获取授权。

授权过期,重新获取登录信息

数据请求肯定是封装好的统一调用。我们规定的是,返回状态为02时,为登录授权失败,需要删除登录信息,然后重新登录,然后再次调用页面初始化。

这时候,需要解决两个问题:

  • 1.如何调用初始化页面
  • 2.多次请求同时发起,多次返回02状态,如何避免多次调用重新登录问题。

对于如何调用初始化页面,我的思路是,在全局方法app.js中,注册一个空对象currentPageInit。在页面初始化数据时,将全局对象currentPageInit指向初始化方法

app.currentPageInit = this.initHandler

在返回数据时,出现需重新登录的状态,则清除目前登录信息,然后调用app.currentPageInit

对于同时多次请求时如何保证只请求一次,我的思路是这样的。

利用Promise,有两个使用方法,多次请求用Promise.all,利用Promise.race判断第一个请求返回的状态。Promise.race之后,立刻关闭调用登录状态。

这时候需要控制两部分内容。在app.js中,配置一个开关,一个条数。Promise.race之后,调整长度,每返回一个就减一,减到一时开关再打开

let PromiseList = [fetchGetProductList, fetchGetPlayMonth, fetchProjectList, fetchStartPlaceList]
Promise.race(PromiseList).then(res => {
  app.currentPageLen = PromiseList.length
  app.currentPageRun = false
})

随机浏览