微信小程式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
onLoad app.globalData.employId =
onLaunch-request-success
要是能等完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] onLaunch sucess callback
下面看下小程式_onLaunch非同步回撥資料載入問題的兩種解決方案
問題
小程式開發過程中,會遇到在App啟動onLaunch的時候,發起登入請求獲取微信使用者資訊,並註冊到我媽自己的伺服器上以便使用,然而,這個過程中,
app on launch -> request -> success -> page onload
是無法判斷success和page onload哪個先來的,會導致頁面初始化資料失敗的情況。
解決方案一
就是在request success中處理,使用getCurrentPages方法獲取是否頁面先於success生成,如果生成我們就強制讓頁面再次渲染。
這顯然是一種hack的方式, 在實際使用過程當中,如果登入邏輯比較複雜,這個方法不是十分便利,page onload在一些特殊情況也會被呼叫,這顯然不是我們想看到的
if (getCurrentPages().length != 0) {
getCurrentPages()[getCurrentPages().length - 1].onLoad()
}
解決方案二
目前我在開發中使用的是這種方案,
在login的邏輯裡,增加一個回撥函式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頁面。
為了幫助大家讓學習變得輕鬆、高效,給大家免費分享一大批資料,幫助大家在成為全棧工程師,乃至架構師的路上披荊斬棘。在這裡給大家推薦一個前端全棧學習交流圈:866109386歡迎大家進群交流討論,學習交流,共同進步。
當真正開始學習的時候難免不知道從哪入手,導致效率低下影響繼續學習的信心。
但最重要的是不知道哪些技術需要重點掌握,學習時頻繁踩坑,最終浪費大量時間,所以有有效資源還是很有必要的。
最後祝福所有遇到瓶疾且不知道怎麼辦的前端程式設計師們,祝福大家在往後的工作與面試中一切順利。