本文探讨微信小程序中App.onLaunch异步请求导致Page.onLoad先执行的问题。通过定义回调函数机制,在App请求成功后通知Page页面更新数据,确保页面初始化依赖的全局变量已就绪,从而避免数据加载失败。
onLaunch异步与onLoad执行顺序问题
按照常规事件触发顺序,小程序初始化时应先执行App实例中的onLaunch方法,随后再执行具体页面Page中的onLoad方法。然而,实际情况中,若在onLaunch内发起网络请求以获取权限状态,由于网络请求的异步特性,Page页面的onLoad事件往往会在请求返回前就已经执行完毕。
问题现象与日志分析
//app.js
App({
onLaunch: function () {
console.log('onLaunch');
wx.request({
url: 'test.php', //仅为示例,并非真实的接口地址
data: {
},
success: function(res) {
console.log('onLaunch-request-success');
// 将employId赋值给全局变量,提供给页面做判断
this.globalData.employId = res.employId;
}
})
},
globalData: {
employId: ''
}
})
//index.js
//获取应用实例
const app = getApp()
Page({
data: {
albumDisabled: true,
bindDisabled: false
},
onLoad: function () {
console.log('onLoad');
console.log('onLoad app.globalData.employId = ' + app.globalData.employId);
//判断是用户是否绑定了
if (app.globalData.employId && app.globalData.employId != '') {
this.setData({
albumDisabled: false,
bindDisabled: true
});
}
})
通过控制台打印日志可以观察到具体的执行时序。
日志输出顺序显示:首先触发onLaunch,紧接着触发onLoad,此时app.globalData.employId尚未赋值,最后才执行onLaunch中的请求成功回调。
理想的执行逻辑应当是等待onLaunch中的网络请求完全结束后,再执行Page的onLoad方法,以确保页面能获取到最新的全局数据。
为解决此时序问题,本文介绍一种基于回调函数的处理方案。
具体做法是:在Page页面中判断当前app.globalData.employId是否存在值。若不存在(即首次加载),则定义一个App层面的回调方法app.employIdCallback = employId => {...}。 。
在App页面的网络请求success回调中,检查是否存在由Page页面定义的回调方法。若存在,则立即执行该方法。由于该回调函数是在Page的作用域内定义的,因此其内部的this指针自然指向Page实例,可直接操作页面数据。
解决方案一:回调函数机制
//app.js
App({
onLaunch: function () {
wx.request({
url: 'test.php', //仅为示例,并非真实的接口地址
data: {
},
success: function(res) {
this.globalData.employId = res.employId;
//由于这里是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.employIdCallback){
this.employIdCallback(res.employId);
}
}
})
},
globalData: {
employId: ''
}
})
//index.js
//获取应用实例
const app = getApp()
Page({
data: {
albumDisabled: true,
bindDisabled: false
},
onLoad: function () {
//判断是用户是否绑定了
if (app.globalData.employId && app.globalData.employId != '') {
this.setData({
albumDisabled: false,
bindDisabled: true
});
} else {
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
app.employIdCallback = employId => {
if (employId != '') {
this.setData({
albumDisabled: false,
bindDisabled: true
});
}
}
}
}
})
采用上述方案后,即可实现预期的执行顺序:先执行App的onLaunch,接着执行Page的onLoad(此时若数据未就绪则注册回调),最后执行App的请求成功回调并触发注册的回调函数。
[App] onLaunch -> [Page] onLoad -> [App] onLaunch sucess callback
以下是关于小程序onLaunch异步回调导致数据加载问题的两种常见解决方案分析。
问题描述:在小程序开发中,常需在App启动时的onLaunch阶段发起登录请求以获取微信用户信息,并注册至自有服务器以便后续使用。
然而,由于网络请求的异步特性,执行流程表现为:
app on launch -> request -> success -> page onload
由于无法确定success回调与page onload的确切先后顺序,若页面初始化逻辑强依赖登录结果,极易导致页面数据加载失败。
解决方案一:强制重新渲染。
该方案在request的success回调中,使用getCurrentPages方法检查页面是否已生成。若页面已存在,则强制调用该页面的onLoad方法以重新渲染。
这显然是一种Hack手段。在实际复杂登录逻辑中,此方法并不便捷,且可能导致page onload在非预期情况下被重复调用,不符合常规开发规范。
解决方案二:强制重新渲染
if (getCurrentPages().length != 0) {
getCurrentPages()[getCurrentPages().length - 1].onLoad()
}
解决方案二:回调函数机制(推荐)。
这是目前开发中较为推荐的方案。
核心思路是在登录逻辑中增加一个回调函数cbLoginCallBack。
Page页面首先判断app.globalData.sessionKey是否存在。若不存在(首次加载),则定义一个App层面的回调方法。
推荐方案:登录回调处理
// Login Request
if (app.cbLoginCallBack) {
typeof app.cbLoginCallBack == 'function' && app.cbLoginCallBack(cb_login.data)
}
// 逻辑页面
if (app.globalData.sessionkey) {
// init data
} else {
app.cbLoginCallBack = res => {
if (res) {
// init data
}
}
}
随后,在App页面的请求success回调中,判断是否存在Page定义的回调方法。若存在,则执行该方法。由于回调函数定义在Page中,其作用域this指向Page页面,从而能正确更新页面状态。
总结:以上介绍了微信小程序中onLaunch异步与首页onLoad执行顺序冲突的解决方法。希望这些内容能帮助大家解决类似困扰。如有任何疑问,欢迎留言交流,小编会及时回复。感谢大家对本站的支持!
以上所述是小编给大家介绍的微信小程序onLaunch异步,首页onLoad先执行?,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对本站网站的支持!