评论

小程序app.onLaunch与page.onLoad异步问题的最佳实践

app.onLaunch与page.onLoad异步问题终极解决方案

场景:

在小程序中大家应该都有这样的场景,在onLaunch里用wx.login静默登录拿到code,再用code去发送请求获取token、用户信息等,整个过程都是异步的,然后我们在业务页面里onLoad去用的时候异步请求还没回来,导致没拿到想要的数据,以往要么监听是否拿到,要么自己封装一套回调,总之都挺麻烦,每个页面都要写一堆无关当前页面的逻辑。

直接上终极解决方案,公司内部已接入两年很稳定:

1.可完美解决异步问题

2.不污染原生生命周期,与onLoad等钩子共存

3.使用方便

4.可灵活定制异步钩子

5.采用监听模式实现,接入无需修改以前相关逻辑

6.支持各种小程序和vue架构

。。。

//为了简洁明了的展示使用场景,以下有部分是伪代码,请勿直接粘贴使用,具体使用代码看Github文档
//app.js
//globalData提出来声明
let globalData = {
  // 是否已拿到token
  token: '',
  // 用户信息
  userInfo: {
    userId: '',
    head: ''
  }
}
//注册自定义钩子
import CustomHook from 'spa-custom-hooks';
CustomHook.install({
 'Login':{
    name:'Login',
    watchKey: 'token',
    onUpdate(token){
      //有token则触发此钩子
      return !!token;
    }
  },
 'User':{
    name:'User',
    watchKey: 'userInfo',
    onUpdate(user){
      //获取到userinfo里的userId则触发此钩子
      return !!user.userId;
    }
  }
}, globalData)
// 正常走初始化逻辑
App({
  globalData,
  onLaunch() {
      //发起异步登录拿token
      login((token)=>{
          this.globalData.token = token
          //使用token拿用户信息
          getUser((user)=>{
             this.globalData.user = user
          })
     })
   }
})
//关键点来了
//Page.js,业务页面使用
Page({
  onLoadLogin() {
       //拿到token啦,可以使用token发起请求了
       const token = getApp().globalData.token
    },

  onLoadUser() {
       //拿到用户信息啦
       const userInfo = getApp().globalData.userInfo
    },

  onReadyUser() {
       //页面初次渲染完毕 && 拿到用户信息,可以把头像渲染在canvas上面啦
       const userInfo = getApp().globalData.userInfo
       // 获取canvas上下文
       const ctx = getCanvasContext2d()
       ctx.drawImage(userInfo.head,0,0,100,100)
    },

  onShowUser() {
       //页面每次显示 && 拿到用户信息,我要在页面每次显示的时候根据userInfo走不同的逻辑
       const userInfo = getApp().globalData.userInfo
       switch(userInfo.sex){
         case 0:
           // 走女生逻辑
           break
         case 1:
           // 走男生逻辑
           break
       }
    }
})


具体文档和Demo见↓

Github:https://github.com/1977474741/spa-custom-hooks

祝大家用的愉快,记得star哦

最后一次编辑于  2023-04-23  
点赞 65
收藏
评论

52 个评论

  • 李艺
    李艺
    2022-03-29
    • 通过劫持原生的Page、App实现,代码比较高级,不是很容易读懂
    • 还支持Vue等框架,这不便于小程序优化瘦身


    JS是作为主线程单线程语言,使用单例模块是不是更简单。在一个独立的LoginManager模块中负责登录与用户信息的拉取,业务代码想用这些信息,直接用异步/同步统一的方式来取,如果信息还没有回来等一下;如果已经有了直接返回,这样是不是逻辑更清晰一些?


    2022-03-29
    赞同
    回复 3
    • Q.ZHANG
      Q.ZHANG
      2022-03-30
      1、因为第一版是vue的版本,后面对小程序写了vue的polyfill。
      2、还行,影响不大,压缩后也就11k。
      这个东西支持组合钩子,所以每个页面的所有钩子都要维护自己的状态,不能用单例。
      这个库的最大优势就是继承了生命周期钩子的使用方式,并且可以自由组合,这两个特点可以把全局数据和页面逻辑完全解耦而且使用也灵活。
      用调用api的方式来使用,还是增加了业务层使用成本,没有钩子使用简单,注册好后在钩子里该怎么拿数据怎么拿数据,不携带具体数据,所以不用写也不用耦合业务相关逻辑(比如在拿信息和存信息的时候调用个什么api)
      2022-03-30
      回复
    • 李艺
      李艺
      2022-03-31回复Q.ZHANG
      “这个库的最大优势就是继承了生命周期钩子的使用方式,并且可以自由组合”,认同
      “用调用api的方式来使用,还是增加了业务层使用成本(比如在拿信息和存信息的时候调用个什么api)”,认同
      两种方案各有优劣,这时候看受众。
      2022-03-31
      回复
    • Q.ZHANG
      Q.ZHANG
      2022-03-31回复李艺
      可以试试,真的很香
      2022-03-31
      回复
  • 。
    2022-03-04

    可以在组件中使用吗

    2022-03-04
    赞同
    回复 11
    • Q.ZHANG
      Q.ZHANG
      2022-03-07
      可以
      2022-03-07
      回复
    • 去码头整点薯条
      去码头整点薯条
      2022-03-29
      组件里具体怎么使用呢,微信小程序的
      2022-03-29
      回复
    • Q.ZHANG
      Q.ZHANG
      2022-03-30回复去码头整点薯条
      vue架构支持,刚看了下原生小程序的情况,现在还不支持原生小程序的组件。
      2022-03-30
      回复
    • milooooooooooooooUp
      milooooooooooooooUp
      2022-04-02回复Q.ZHANG
      uniapp打包出的字节和支付宝组件中也无法使用  微信的可以 有办法处理吗
      2022-04-02
      回复
    • Q.ZHANG
      Q.ZHANG
      2022-04-28回复milooooooooooooooUp
      最新版已经兼容了支付宝和字节组件内使用
      2022-04-28
      回复
    查看更多(6)

正在加载...

登录 后发表内容