最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

typescript - APP_INITIALIZER - TypeError: appInits is not a function Angular 18 - Stack Overflow

programmeradmin3浏览0评论

I have a standalone angular 18 application with bootstraping:

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideAnimations(), // required animations providers
    provideToastr(), // Toastr providers
    {
      provide: APP_INITIALIZER,
      useFactory: onAppStart,
      multi: true,
    },
  ],
};

my OnAppStart function:

export function onAppStart(): Promise<any> {
  const router = inject(Router);
  const userService = inject(UserService);
  return new Promise(async (resolve) => {
    await userService.InitUserProfile().pipe(
      tap(
        (r) => {
          if (r == undefined) {
            router.navigate(['/']);
          }
        },
        (e) => console.error(e)
      )
    );

    resolve(true);
  });
}

userService method

  public InitUserProfile(): Observable<UserDataModel | undefined> {
    return from(
      this.client
        .get(
          new GetUserDataRequest({
            evoCode: localStorage.getItem('user.evo') ?? '',
          })
        )
        .then((r) => {
          if (r.model.email) {
            this.userData.set(r.model);
            return r.model;
          }
          return undefined;
        })
    );
  }

After startup I get this error and i dont know why

main.ts:5 ERROR TypeError: appInits is not a function
    at _ApplicationInitStatus.runInitializers (core.mjs:31480:26)
    at core.mjs:33209:18
    at _callAndReportToErrorHandler (core.mjs:31571:20)
    at core.mjs:33207:12
    at _ZoneDelegate.invoke (zone.js:369:28)
    at Object.onInvoke (core.mjs:7048:25)
    at _ZoneDelegate.invoke (zone.js:368:34)
    at ZoneImpl.run (zone.js:111:43)
    at _NgZone.run (core.mjs:6900:24)
    at bootstrap (core.mjs:33163:17)

I want to load a user from server on startup of the application. This does not seem to work. Can you help me why?

I have a standalone angular 18 application with bootstraping:

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideAnimations(), // required animations providers
    provideToastr(), // Toastr providers
    {
      provide: APP_INITIALIZER,
      useFactory: onAppStart,
      multi: true,
    },
  ],
};

my OnAppStart function:

export function onAppStart(): Promise<any> {
  const router = inject(Router);
  const userService = inject(UserService);
  return new Promise(async (resolve) => {
    await userService.InitUserProfile().pipe(
      tap(
        (r) => {
          if (r == undefined) {
            router.navigate(['/']);
          }
        },
        (e) => console.error(e)
      )
    );

    resolve(true);
  });
}

userService method

  public InitUserProfile(): Observable<UserDataModel | undefined> {
    return from(
      this.client
        .get(
          new GetUserDataRequest({
            evoCode: localStorage.getItem('user.evo') ?? '',
          })
        )
        .then((r) => {
          if (r.model.email) {
            this.userData.set(r.model);
            return r.model;
          }
          return undefined;
        })
    );
  }

After startup I get this error and i dont know why

main.ts:5 ERROR TypeError: appInits is not a function
    at _ApplicationInitStatus.runInitializers (core.mjs:31480:26)
    at core.mjs:33209:18
    at _callAndReportToErrorHandler (core.mjs:31571:20)
    at core.mjs:33207:12
    at _ZoneDelegate.invoke (zone.js:369:28)
    at Object.onInvoke (core.mjs:7048:25)
    at _ZoneDelegate.invoke (zone.js:368:34)
    at ZoneImpl.run (zone.js:111:43)
    at _NgZone.run (core.mjs:6900:24)
    at bootstrap (core.mjs:33163:17)

I want to load a user from server on startup of the application. This does not seem to work. Can you help me why?

Share Improve this question asked Feb 17 at 7:21 MikeMike 1741 silver badge10 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

You should define a factory function, that return another function which returns a promise. The definition will look like below.

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideAnimations(), // required animations providers
    provideToastr(), // Toastr providers
    {
      provide: APP_INITIALIZER,
      useFactory: onAppStart,
      deps: [Router, UserService], // <- notice the deps
      multi: true,
    },
  ],
};

Then define the onAppStart to return a function that uses these dependencies, which are provided as function arguments:

We can use firstValueFrom from rxjs to convert the observable to a promise:

export function onAppStart(router: Router, userService: UserService): Promise<any> {
  return () => 
    firstValueFrom(
      userService.InitUserProfile().pipe(
        tap(
          (r) => {
            if (r == undefined) {
              router.navigate(['/']);
            }
          },
          (e) => console.error(e)
        )
      )
    );
}

To further simplify the code you can make the service return a promise:

public InitUserProfile(): Observable<UserDataModel | undefined> {
  return this.client
    .get(
      new GetUserDataRequest({
        evoCode: localStorage.getItem('user.evo') ?? '',
      })
    )
    .then((r) => {
      if (r.model.email) {
        this.userData.set(r.model);
        return r.model;
      }
      return undefined;
    });
}

Then the app initializer callback can be simplified to:

export function onAppStart(router: Router, userService: UserService): Promise<any> {
  return () => userService.InitUserProfile().then((r) => {
    if (r == undefined) {
      router.navigate(['/']);
    }
  })
  .catch(err => console.log(err));
}
发布评论

评论列表(0)

  1. 暂无评论