小程序使用Object.defineProperty解决onLaunch与onLoad异步问题

1,191 阅读2分钟

最近写小程序时遇到个问题,就是在app.js做登录的时,还没有登录完成就执行了页面的onLoad


一、刨析

wx.login 是异步函数所以说在没有返回结果的时候还会继续往下执行

解决办法就是

  1. 先创建一个全局变量,
  2. 在app.js 创建一个watch函数通过Object.defineProperty监听全局变量的改变
  3. 在onLaunch里执行登录 登录完成后改变全局变量里的值
  4. 在其他页面js里调用app里的watch 监听着全局变量
  5. 全局变量一改变就继续往后执行页面上的函数
  6. 注意的几点就是 登录完成修改全局变量的值 跟 其他页面要加一个判断是否已经登录完成的条件 不然已经登录过的用户 直接访问页面是不会往后执行的

    if (wx.getStorageSync('token')) {  // 已经登录 直接执行业务逻辑  return;}   

二、上代码

在app.js 里

/**   
  * 登录 
  */  
login() {    
  console.log('login~~~');
  const that = this;  
  wx.login({   
    success: res => {     
      // 发送 res.code 到后台换取 openId, sessionKey, unionId
      // 执行你们后台的login        
      that.globalData.http.request({     
        url: "/user/wxLogin",     
        type: "post",      
        data: {       
          code: res.code,      
          agent: that.globalData.id          
        },        
      }).then(res => {
        // 重点在返回的时候设置storage 跟 修改globalData.id 为 任何数都行 我修改成了用户id         
        wx.setStorageSync("token", res.data.data.sessionId);      
        that.globalData.id = res.data.data.user.id;      
      });   
    }    
  })  
},

onLaunch: function (options) {  
  console.log('app.js');  
  wx.checkSession({   
    success() {     
      //session_key 未过期,并且在本生命周期一直有效    
      if (!wx.getStorageSync('token')) {      
        that.login();   
      }  
    },    
    fail() {  
      // session_key 已经失效,需要重新执行登录流程     
      // 登录   
      that.login();    
    }  
  })
},

// 监听id属性
watch: function (method) { 
  var obj = this.globalData;
  // 使用Object.defineProperty 监听this.globalData.id的变化
  Object.defineProperty(obj, "id", {  
    configurable: true,  
    enumerable: true,  
    set: function (value) {   
      console.log(value, 'lxxxxxxxxx');  
      this._uid = value; 
      method(value);   
    },  
    get: function () {   
      return this._uid 
    } 
  })
},

在details.js

const self = this;
if (wx.getStorageSync('token')) {
  self.getData();
  return;
}
console.log('登陆流程尚未完成,id是:',app.globalData.id)
// 调用app.js 里的watch 方法
app.watch(function(id){
  console.log("登陆流程已完成,新的id是:", id)
  console.log('登陆流程已完成,新的app.globalData.id是:', app.globalData.id)
  // 此处执行登陆后的业务  self.getData(); 
})



有啥不清楚的可以在下方评论~~

有更好更简单的方法也欢迎在下方评论 互相学习~~