app.onLaunch与page.onLoad异步问题
发布于 3 年前 作者 zhujuan 1614 次浏览 来自 分享

问题:

相信很多人都遇到过这个问题,通常我们会在应用启动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属性
    watchfunction (fn{
        var obj = this.globalData
        Object.defineProperty(obj, 'hasLogin', {
          configurabletrue,
          enumerabletrue,
          setfunction (value{
            this._hasLogin = value;
            fn(value);
          },
          getfunction () {
            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(() => {
        // 进行一些需要登录态的操作...
      })
    },
});

具体实现

具体实现可以参考我的商城小程序项目

项目体验地址:体验

代码:代码

回到顶部