1. 程式人生 > >微信小程式onLaunch非同步,首頁onLoad先執行?

微信小程式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歡迎大家進群交流討論,學習交流,共同進步。

當真正開始學習的時候難免不知道從哪入手,導致效率低下影響繼續學習的信心。

但最重要的是不知道哪些技術需要重點掌握,學習時頻繁踩坑,最終浪費大量時間,所以有有效資源還是很有必要的。

最後祝福所有遇到瓶疾且不知道怎麼辦的前端程式設計師們,祝福大家在往後的工作與面試中一切順利。
在這裡插入圖片描述