鹅鹅鹅鹅
鹅鹅鹅鹅
  • 发布:2022-01-12 14:29
  • 更新:2024-05-10 18:33
  • 阅读:4408

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

分类:uni-app

场景:

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

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

1.可完美解决异步问题

2.使用方便

3.可灵活定制异步钩子

4.采用监听模式实现,接入无需修改以前代码

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

。。。

//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  
    },  
    onReadyShowUser(){  
        //小程序内页面渲染完成 && 页面显示 && 拿到用户信息  
        //Tips:适用于需要获取小程序组件或者dom,并且每次页面显示都会执行的场景,例如,每次显示页面的时候都要拿到最新的头像去渲染到canvas上面  
    },  
})

具体文档和Demo见↓

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

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

2 关注 分享
j***@qq.com 1***@qq.com

要回复文章请先登录注册

5***@qq.com

5***@qq.com

封装一个 users 方法挂到 uni.$xxx ,在 onShow await uni.$xxx.users() ,这样就可以了。
2022-06-16 17:23
鹅鹅鹅鹅

鹅鹅鹅鹅 (作者)

回复 者行孙 :
也可以,异步业务不多不复杂这样没问题
2022-04-11 19:20
者行孙

者行孙

在每次onShow或onShow之后登录成功刷新数据:
```javascript
{
onShow() {
this.isShow = true;
this.getData();
},
onLoad() {
eventBus.on("login", this.getData); // 监听登录
},
onUnload() {
eventBus.off("login", this.getData); // 取消监听登录
},
methods: {
getData() {
if (!userInstance.token || !this.isShow) return;
// 业务逻辑
},
}
}
```
2022-04-11 16:49
鹅鹅鹅鹅

鹅鹅鹅鹅 (作者)

回复 者行孙 :
这样当然可以,没问题,使用成本会大些,每个页面都要去写相同的监听逻辑。
而且注册一个回调只能解决一个异步任务,比如有些页面需要Login又需要异步获取的位置,你要注册两个回调嵌套,总之业务越复杂代码也越复杂。
再说个场景,需要在每次onShow的时候拿token获取数据刷新页面,要把eventBus.on("login", this.onLogin);这个监听逻辑写在onShow里,可行吗。
如果你们的业务没这么复杂,而且这种异步通知涉及的页面比较少,用eventBus就挺好,毕竟自己比较熟悉
2022-04-11 10:36
者行孙

者行孙

更简单的做法,已经可用满足大多数应用场景了。
```
watchEffect(() => {
if (userInstance.token) return;
// 业务逻辑
});
```
2022-04-09 12:29
者行孙

者行孙

通知用 `EventBus` 啊, 登录成功时 `eventBus.emit("login")`,需要监听的地方用 `eventBus.on("login", callback)` 完事了。
```
onLoad() {
if (userInstance.token) this.onLogin(); // 已经登录
eventBus.on("login", this.onLogin); // 监听登录
},
onUnload() {
eventBus.off("login", this.onLogin); // 取消监听登录
},
methods: {
onLogin() {
// 业务逻辑
},
}
```
2022-04-09 11:58
鹅鹅鹅鹅

鹅鹅鹅鹅 (作者)

回复 者行孙 :
vuex只是个状态存储管理工具,通知逻辑需要你自己写,并且每个页面都要写
2022-04-08 15:00
1***@qq.com

1***@qq.com

2022-04-08 14:42
鹅鹅鹅鹅

鹅鹅鹅鹅 (作者)

回复 者行孙 :
不是一回事,这个是创建一个相应对象,可监听,vuex本身就可响应可监听
2022-04-08 14:34
者行孙

者行孙

或者用 Vuex 封装一下用户状态,也很简单
2022-04-08 12:38