评论

小程序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  
点赞 62
收藏
评论

48 个评论

  • Shawshank_King
    Shawshank_King
    2022-11-21

    以后就用这个方案了

    2022-11-21
    赞同 4
    回复 1
    • Api调用师
      Api调用师
      2023-03-10
      感谢支持
      2023-03-10
      回复
  • Dulk
    Dulk
    2023-12-02

    用上了,感谢up!!

    2023-12-02
    赞同 3
    回复
  • 🍼_Jack_Lu
    🍼_Jack_Lu
    2022-08-16

    确实这两年想过用很多方法,查看了promise的实现,做过多模块用同时登录,返回同一个promise,试过每个页面设置重新查找登录,都不好实现,楼主做得确实好!

    2022-08-16
    赞同 2
    回复 1
    • Api调用师
      Api调用师
      2022-08-18
      栓Q,很好用的,用起来吧
      2022-08-18
      回复
  • locter
    locter
    11-01

    这个解决方案简直太棒了,不过好奇你是怎么把那些更新的函数加到每个页面中的?

    11-01
    赞同 1
    回复 1
  • Judy
    Judy
    2023-04-20

    使用下来,比较麻烦。直接自动登录后,获取当前page,调用page.onShow()方法比较简单粗暴。(把跟登录相关需要更新的方法调用写在onShow里

    2023-04-20
    赞同 1
    回复 7
    • Api调用师
      Api调用师
      2023-04-20
      这样会阻塞整个onShow,如果你onShow中只有一部分逻辑依赖登陆,那后续跟登陆无关的逻辑也会被影响到。
      还有如果你的项目比较简单,场景特别单一,而且也不用考虑扩展性的话,那其实只要能实现效果,怎样都行。
      2023-04-20
      2
      回复
    • Api调用师
      Api调用师
      2023-04-20
      总结一下,有以下三点吧
      1.和原生钩子耦合问题。
      2.应用场景比较单一,不易扩展。
      3.不能组合使用,不灵活。
      当然这三点都不是实现一个需求的必要条件,所以。。还是自己看情况用哪种比较合适
      2023-04-20
      回复
    • 元芳
      元芳
      2023-08-06回复Api调用师
      已经Star,希望能持续维护
      2023-08-06
      1
      回复
    • 元芳
      元芳
      2023-08-06回复Api调用师
      原生小程序组件现在支持了吗
      2023-08-06
      1
      回复
    • Api调用师
      Api调用师
      2023-08-07回复元芳
      害,还不支持
      2023-08-07
      回复
    查看更多(2)
  • Judy
    Judy
    2023-03-09

    必须赞一个

    2023-03-09
    赞同 1
    回复 1
    • Api调用师
      Api调用师
      2023-03-10
      感谢支持
      2023-03-10
      回复
  • 华湘
    华湘
    2023-02-28

    Promise赞一个

    2023-02-28
    赞同 1
    回复 1
    • Api调用师
      Api调用师
      2023-02-28
      感谢支持,但是没有用Promise哦
      2023-02-28
      回复
  • 你的名字
    你的名字
    2022-07-21

    牛,这是我苦苦追寻多年的答案,想问下大佬是在深圳工作吗?

    2022-07-21
    赞同 1
    回复 3
    • Api调用师
      Api调用师
      2022-07-21
      哈哈,这么巧想到一块儿了。对啊,这你都知道?
      2022-07-21
      回复
    • 你的名字
      你的名字
      2022-07-22回复Api调用师
      不是,这个问题苦恼我多年了,一直找不到优雅的解决方案,直到无意中看到你这篇文章,当时激动的心情难以言表,对大佬佩服的五体投地。想问下你公司是做健身行业的吗?
      2022-07-22
      1
      回复
    • Api调用师
      Api调用师
      2022-07-22回复你的名字
      谢谢谢谢,不是,我们公司是婚恋行业的
      2022-07-22
      回复
  • 修亮
    修亮
    2022-06-23

    优秀

    2022-06-23
    赞同 1
    回复 1
    • Api调用师
      Api调用师
      2022-06-24
      是吧🐱💻
      2022-06-24
      回复
  • vking
    vking
    2022-06-15

    优秀

    2022-06-15
    赞同 1
    回复 1
    • Api调用师
      Api调用师
      2022-06-16
      感谢支持
      2022-06-16
      回复

正在加载...

登录 后发表内容