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 badges1 Answer
Reset to default 2You 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));
}