前言
onLaunch
与onLoad
的异步问题,onLaunch
里的请求数据还没拿到,onLoad
中就执行了。- 热启动小程序时
onLaunch
不执行,app
没有提供针对于页面的全局前置处理钩子。
其实也不止是onLaunch
与onLoad
这两个钩子异步导致的顺序问题,当页面使用的自定义组件内部也在其生命周期中进行了一些请求,那么就不止是页面onLoad
钩子执行顺序的问题了,而涉及到了 app
、页面
、组件
三方的生命周期执行顺序问题。
这些典型的问题一直是很多小程序开发者的困扰,网上很多解决方案都需要针对一个个页面进行大量的改动,总是差点意思。
而现在,我彻底的解决了这些问题,并且改动极少,只需在 app
里添加几行代码即可,其它页面无需任何改动,真正做到零成本解决问题,我把这些解决方案写成了一个js库,它叫wxbuf
。
github仓库,欢迎star: https://github.com/laivv/wxbuf
现在,我们使用wxbuf
来解决上面两个典型的问题,以下假定你已经在项目中导入了wxbuf
库
onLaunch与onLoad的异步问题
wxbuf
支持app
的onLaunch
钩子返回promise
来推迟整个app、页面、组件的所有生命周期执行。
也就是说,所有的生命周期都要等到onLaunch
执行完毕并且是Fulfilled(已成功)
状态才会执行,我们把这个功能叫异步onLaunch
。
异步onLaunch
默认关闭, 需要在app.js
中配置开启后方可使用
示例:
// app.js
// 导入wxbuf
import wxbuf from 'wxbuf'
// 配置wxbuf
wxbuf.config({
asyncOnLaunch: true // 开启异步onLaunch支持
})
App({
async onLaunch() {
// 请确保返回的`promise`最终会是`Fulfilled(已成功)`状态,否则整个app将永远不会被加载
try {
const res = await fetch('/api/user')
//...
}catch(e) {}
}
})
由此,整个app、页面及组件的生命周期都将在onLaunch
执行完毕并且是Fulfilled(已成功)
状态时才会继行续执行,确保了页面onLoad
或组件created
、attached
等生命周期中一定能获取到正确的数据。
onLoad的问题
由于onLaunch
只在冷启动阶段执行,通过热启动小程序进入指定页面的时候不再执行,因此需要一个全局并针对于页面统一处理的前置处理钩子,类似于上面的异步onLaunch
那样。
wxbuf
支持在app
中配置onPageInit
钩子,通过它返回promise
来推迟页面和面页上的组件所有生命周期执行。
也就是说,所有的页面及其组件的生命周期都要等到onPageInit
执行完毕并且是Fulfilled(已成功)
状态才会执行。
wxbuf
还支持在页面配置onInit
钩子,和上述onPageInit
功能一样,区别是onInit
是写在页面上的,也只作用于当前页面。
以上两个钩子默认关闭, 需要在app.js
中配置开启,开启后方可在app
中使用onPageInit
、页面中使用onInit
示例:
// app.js
// 导入wxbuf
import wxbuf from 'wxbuf'
// 配置wxbuf
wxbuf.config({
pageOnInit: true // 开启pageOnInit
})
App({
onPageInit(page, options) {
// 请确保返回的`promise`最终会是`Fulfilled(已成功)`状态,否则所有页面和组件将永远不会被加载
return new Promise((resolve) => setTimeout(() => resolve(), 1000))
}
})
// page代码
Page({
onInit(options) {
// 请确保返回的`promise`最终会是`Fulfilled(已成功)`状态,否则当前页面及其组件将永远不会被加载
return new Promise((resolve) => setTimeout(() => resolve(), 1000))
},
})
执行顺序
总结一下执行顺序:
app.onLaunch
-> app.其它钩子
app.onLaunch
-> app.onPageInit(如果有)
-> page.onInit(如果有)
-> page.其它钩子
app.onLaunch
-> app.onPageInit(如果有)
-> page.onInit(如果有)
-> component.其它钩子
以上所有后面的钩子都将依次等待它前面的钩子执行完毕并且是Fulfilled(已成功)
状态才会执行,因此建议加上错误处理防止后续生命周期被锁死