Ionic 3应用:闪屏阶段、device ready前执行代码的需求
在Ionic 3闪屏阶段提前加载用户数据的方案
完全可以利用闪屏显示的这段时间来并行获取用户数据,把原本串行的操作改成并行,就能省下那2秒的时间。下面是具体的实现步骤和思路:
核心思路
原来的代码是等platform.ready()完成后才开始读取存储、初始化用户数据,这是串行执行。我们可以把读取存储的操作提前启动,和platform.ready()的执行并行进行,这样两者的耗时可以重叠,从而减少总等待时间。同时,我们需要手动控制闪屏的隐藏时机,确保数据初始化完成后再让用户看到应用页面。
步骤1:修改闪屏配置
首先在config.xml里关闭闪屏的自动隐藏,避免它在数据准备好之前就消失:
<!-- 关闭自动隐藏闪屏 --> <preference name="AutoHideSplashScreen" value="false" /> <!-- 设置一个足够长的超时时间,防止意外提前隐藏 --> <preference name="SplashScreenDelay" value="10000" />
步骤2:修改AppModule代码
我们需要提前启动存储读取操作,同时等待平台准备好,最后在数据初始化完成后手动隐藏闪屏:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { IonicModule, IonicApp } from 'ionic-angular'; import { MyApp } from './app.component'; import { Storage } from '@ionic/storage'; import { SplashScreen } from '@ionic-native/splash-screen'; import { StatusBar } from '@ionic-native/status-bar'; @NgModule({ declarations: [MyApp], imports: [BrowserModule, IonicModule.forRoot(MyApp)], bootstrap: [IonicApp], entryComponents: [MyApp], providers: [StatusBar, SplashScreen, Storage] }) export class AppModule { constructor( private platform: Platform, private storage: Storage, private splashScreen: SplashScreen, private statusBar: StatusBar ) { // 提前启动读取token的操作,不用等platform.ready() const tokenFetchPromise = this.storage.get('id_token'); // 同时等待平台准备就绪 this.platform.ready().then(async () => { this.statusBar.styleDefault(); // 等待token读取完成 const token = await tokenFetchPromise; // 执行用户数据初始化,这里改成async/await更清晰 await this.initUserData(token); // 所有准备工作完成后,手动隐藏闪屏 this.splashScreen.hide(); }); } // 把初始化函数改成异步,确保我们能等待它完成 private async initUserData(token: string | null) { // 这里替换成你实际的用户数据初始化逻辑(比如调用API拉取数据) // 模拟2秒的耗时操作 await new Promise(resolve => setTimeout(resolve, 2000)); console.log('用户数据初始化完成,现在可以显示页面了'); } }
备选方案:使用Angular的APP_INITIALIZER
如果你希望确保用户数据在Angular应用初始化完成前就准备好,可以用Angular的APP_INITIALIZER钩子,它会阻塞页面渲染直到初始化完成,闪屏会一直显示到这个过程结束:
import { NgModule, APP_INITIALIZER } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { IonicModule, IonicApp } from 'ionic-angular'; import { MyApp } from './app.component'; import { Storage } from '@ionic/storage'; import { SplashScreen } from '@ionic-native/splash-screen'; import { StatusBar } from '@ionic-native/status-bar'; // 定义初始化函数,必须返回Promise export async function initApp(storage: Storage, platform: Platform) { await platform.ready(); const token = await storage.get('id_token'); // 调用你的用户数据初始化逻辑 await initUserData(token); } // 如果你把initUserData放在服务里,记得把服务加到deps里 export async function initUserData(token: string | null) { // 实际的初始化逻辑 await new Promise(resolve => setTimeout(resolve, 2000)); } @NgModule({ declarations: [MyApp], imports: [BrowserModule, IonicModule.forRoot(MyApp)], bootstrap: [IonicApp], entryComponents: [MyApp], providers: [ StatusBar, SplashScreen, Storage, { provide: APP_INITIALIZER, useFactory: initApp, deps: [Storage, Platform], multi: true } ] }) export class AppModule {}
注意事项
- 确保
initUserData是异步的,这样我们能准确等待它完成,避免页面显示后数据还没准备好的问题。 - 如果你的存储依赖特定平台的API(比如iOS的Keychain),
storage.get()可能会在platform.ready()完成后才真正执行,但没关系,并行操作依然能节省时间。 - 不要把
SplashScreenDelay设置得太短,否则超时后闪屏会强制隐藏,可能导致页面显示时数据还没准备好。
内容的提问来源于stack exchange,提问作者Ciprian Dragoe
相关产品推荐
相关产品推荐

