Búsqueda de sitios web

typescript - APP_INITIALIZER conduce a una página en blanco sin errores en Angular 12 (funcionaba desde la versión 9 hasta la 11)


Necesitamos algunos servicios en nuestra aplicación desde el principio. Por lo tanto, tenemos algunos proveedores que los inicializan al iniciar. Esto es de la sección providers en app.module.ts:

providers: [
  { provide: MAT_DATE_LOCALE, useValue: 'en-US' },
  {
    provide: APP_INITIALIZER,
    useFactory: (service: MetaService) => () => service,
    deps: [MetaService],
    multi: true
  }
],

Esto funcionó bien en Angular 9-11. Sin embargo, después de actualizar a Angular 12 e incluso en un proyecto Angular 12 en blanco, esto parece romper la aplicación.

El servicio se crea, sin embargo. Se registra correctamente usando esto:

useFactory: (service: MetaService) => () => { console.log(service); return service; },

Sin embargo, la página vuelve en blanco. No se renderiza ningún componente, no ocurrió ningún enrutamiento.

No hay errores en la CLI y nada en la consola del navegador, solo una página en blanco. Cuando quito el proveedor, parece funcionar bien.

¿Cambió cómo funciona APP_INITIALIZER en Angular 12? ¿Cómo arreglar o actualizar el código para que funcione de nuevo? Tal vez haya una mejor manera de inicializar servicios al arrancar de todos modos?

Respuesta #1

Angular cambió la funcionalidad del inicializador de aplicaciones para permitir Observables así como Promesas. Lo que también ha cambiado es la especificidad del token de inyección, que espera una función que devuelva una promesa, un observable o void. Así que, por ahora, tu código es incorrecto ya que estás devolviendo un servicio en lugar de uno de los tipos esperados. Eso todavía no explica qué está saliendo mal.

Angular solía solo verificar si la función de fábrica para cada inicializador devolvía una promesa y la agregaba a un arreglo de promesas para ejecutar con Promise.all(). Ahora, también verifica si es un observable y lo convierte en una promesa envolviendo una llamada a subscribe en una promesa y vinculando los callbacks de complete y error del Observable a los callbacks de resolve y reject de la promesa.

Si tienes un método llamado subscribe en tu servicio, entonces esto haría que tu servicio pasara la protección isSubscribable de Angular. Luego Angular trataría tu servicio como un Observable e intentaría convertirlo en una promesa de la manera mencionada anteriormente. (Si tienes un método then, eso también causaría un problema, aunque es poco probable dado que tu código funcionaba antes). La promesa nunca se resolvería y eso conduciría al comportamiento que estás describiendo.

No hay otra razón que pueda imaginar que cause este problema dado el código que has compartido. Al menos, simplemente cambia la definición de la fábrica para que devuelva void y deberías estar bien.

useFactory: (service: MetaService) => () => { }