app.onLaunch与page.onLoad异步问题
问题:
相信很多人都遇到过这个问题,通常我们会在应用启动app.onLaunch() 去发起静默登录,同时我们需要在加载页面的时候,去调用一个需要登录态的后端 API 。由于两者都是异步,往往page.onload()调用API的时候,app.onLaunch() 内调用的静态登录过程还没有完成,从而导致请求失败。
解决方案:
1. 通过回调函数
// on app.js
App({
onLaunch() {
login()
// 把hasLogin设置为 true
.then(() => {
this.globalData.hasLogin = true;
if (this.checkLoginReadyCallback) {
this.checkLoginReadyCallback();
}
})
// 把hasLogin设置为 false
.catch(() => {
this.globalData.hasLogin = false;
});
},
});
// on page.js
Page({
onLoad() {
if (getApp().globalData.hasLogin) { // 登录已完成
fn() // do something
} else {
getApp().checkLoginReadyCallback = () => {
fn()
}
}
},
});
⚠️注意:这个方法有一定的缺陷(如果启动页中有多个组件需要判断登录情况,就会产生多个异步回调,过程冗余),不建议采用。
2. 通过Object.defineProperty监听globalData中的hasLogin值
// on app.js
App({
onLaunch() {
login()
// 把hasLogin设置为 true
.then(() => {
this.globalData.hasLogin = true;
})
// 把hasLogin设置为 false
.catch(() => {
this.globalData.hasLogin = false;
});
},
// 监听hasLogin属性
watch: function (fn) {
var obj = this.globalData
Object.defineProperty(obj, 'hasLogin', {
configurable: true,
enumerable: true,
set: function (value) {
this._hasLogin = value;
fn(value);
},
get: function () {
return this._hasLogin
}
})
},
});
// on page.js
Page({
onLoad() {
if (getApp().globalData.hasLogin) { // 登录已完成
fn() // do something
} else {
getApp().watch(() => fn())
}
},
});
3. 通过beautywe的状态机插件(项目中使用该方法)
// on app.js
import { BtApp } from '@beautywe/core/index.js';
import status from '@beautywe/plugin-status/index.js';
import event from '@beautywe/plugin-event/index.js';
const app = new BtApp({
onLaunch() {
// 发起静默登录调用
login()
// 把状态机设置为 success
.then(() => this.status.get('login').success())
// 把状态机设置为 fail
.catch(() => this.status.get('login').fail());
},
});
// status 插件依赖于 beautywe-plugin-event
app.use(event());
// 使用 status 插件
app.use(status({
statuses: [
'login'
],
}));
// 使用原生的 App 方法
App(app);
// on page.js
Page({
onLoad() {
// must 里面会进行状态的判断,例如登录中就等待,登录成功就直接返回,登录失败抛出等。
getApp().status.get('login').must().then(() => {
// 进行一些需要登录态的操作...
})
},
});
具体实现
具体实现可以参考我的商城小程序项目
项目体验地址:体验
代码:代码