评论

🚀 小程序初始化异步问题优雅解决!发布-订阅模式实战分享 🌈✨

实战中踩到的坑!💥 小程序 onLaunch 初始化完,首页却提前跑?数据拿不到直接翻车!我用 发布订阅 + Promise,彻底解决这个老问题,附上完整实现,拿去即用!✔️

开发小伙伴们 👋,是不是也踩过这个坑👇:小程序刚启动时在 app.js 做全局初始化,但首页 onLoad 取不到初始化后的数据,导致页面逻辑出错!

我用 Promise + 发布订阅模式,完美解决!💥


🌟 小程序启动时,我需要在 onLaunch() 做这些事:

✅ 检查小程序更新 ✅ 拉取基础配置 ✅ 获取用户或系统状态

BUT!初始化是 异步 的,而首页 index.js 的 onLoad() 生命周期太快,可能比初始化还早一步。直接用 getApp() 拿不到数据,页面全空 ❌。💡 解决方案: 用发布订阅模式通知页面 —— 初始化完成再动!


🔥 实现核心:

1️⃣ Promise 封装初始化,明确完成时机 2️⃣ 自己实现简易版 EventBus,支持 on / emit 3️⃣ 初始化成功后 emit 发布事件,页面收到通知,再用数据


📄 步骤拆解:

1️⃣ 封装初始化函数 📌 重点:重试机制,确保 getApp() 可用。

// utils/appInit.js
function initFun() {
  const app = getApp();
  app.globalData.pageInit = true;
}

function appInit(maxRetry = 10, interval = 250) {
  return new Promise((resolve, reject) => {
    let retryCount = 0;
    const checkAppReady = () => {
      wx.nextTick(() => {
        if (typeof getApp === 'function' && getApp() !== undefined) {
          initFun();
          resolve('初始化成功');
        } else if (retryCount < maxRetry) {
          retryCount++;
          setTimeout(checkAppReady, interval);
        } else {
          reject('初始化失败');
        }
      });
    };
    checkAppReady();
  });
}

export default appInit;




2️⃣ 实现简易版 EventBus 📌 功能:订阅 on / 发布 emit / 取消 off,页面间轻松通信。

// utils/eventBus.js
class EventBus {
  constructor() {
    this.events = {};
  }

  on(event, callback) {
    if (typeof event !== 'string' || typeof callback !== 'function') return;
    if (!this.events[event]) {
      this.events[event] = [];
    }
    if (!this.events[event].includes(callback)) {
      this.events[event].push(callback);
    }
  }

  emit(event, data) {
    if (!this.events[event] || this.events[event].length === 0) return;
    this.events[event].forEach(cb => {
      try {
        cb(data);
      } catch (err) {
        console.error(`"${event}" 回调出错`, err);
      }
    });
  }

  off(event, callback) {
    if (!this.events[event]) return;
    this.events[event] = this.events[event].filter(fn => fn !== callback);
  }
}

const eventBus = new EventBus();
export default eventBus;




3️⃣ App.js 使用 📌 关键点:✅ 先订阅,再初始化,防止订阅晚了漏事件。

// app.js
import appInit from '/utils/appInit';
import eventBus from '/utils/eventBus';

App({
  globalData: {},
  onLaunch() {
    // 先订阅,保证其他页面后续能接收
    eventBus.on('initDone', () => {});

    appInit(10).then(() => {
      eventBus.emit('initDone', { init: true });
    }).catch(err => {
      console.error('App 初始化失败', err);
    });
  },
});




4️⃣ 首页 index.js 监听初始化完成 📌 确保数据 ready,再做业务处理!

// pages/index/index.js
import eventBus from '/utils/eventBus';

Page({
  onLoad() {
    eventBus.on('initDone', () => {
      const app = getApp();
      console.log('收到初始化完成通知', app.globalData);
      // 使用初始化数据
    });
  },

  onUnload() {
    // 页面销毁时解绑,防止内存泄漏
    eventBus.off('initDone', ()=>{});
  }
});

最后一次编辑于  03-20  
点赞 1
收藏
评论
登录 后发表内容